<commit_before>/*!
    \file service.h
    \brief Asio service definition
    \author <NAME>
    \date 16.12.2016
    \copyright MIT License
*/

#ifndef CPPSERVER_ASIO_SERVICE_H
#define CPPSERVER_ASIO_SERVICE_H

#include "asio.h"
#include "memory.h"

#include "threads/thread.h"

#include <atomic>
#include <cassert>
#include <memory>
#include <string>
#include <vector>

namespace CppServer {
namespace Asio {

//! Asio service
/*!
    Asio service is used to host all clients/servers based on Asio C++ library.
    It is implemented based on Asio C++ Library and use one or more threads to
    perform all asynchronous IO operations and communications.

    There are three ways to initialize Asio service:

    1) Service(threads, false) - initialize a new Asio service with io-service-
    per-thread design. In this case each Asio IO will be bounded to its own
    working thread and all handlers will be dispatched sequentially without
    strands making the code clean and easy to maintain.

    2) Service(threads, true) - initialize a new Asio service with thread-pool
    design. In this case single Asio IO will be bounded to all threads in pool,
    but strands will be required to serialize handler execution.

    3) Service(service, true | false) - initialize a new Asio service using the
    existing Asio IO service instance with required strands flag. Strands are
    required for serialized handler execution when single Asio IO service used
    in thread pool.

    Thread-safe.

    http://think-async.com
*/
class Service : public std::enable_shared_from_this<Service>
{
public:
    //! Initialize Asio service with single or multiple working threads
    /*!
        \param threads - Working threads count (default is 1)
        \param pool - Asio service thread pool flag (default is false)
    */
    explicit Service(int threads = 1, bool pool = true);
    //! Initialize Asio service manually with a given Asio IO service
    /*!
        \param service - Asio IO service
        \param strands - Asio IO service strands required flag (default is false)
    */
    explicit Service(std::shared_ptr<asio::io_service> service, bool strands = false);
    Service(const Service&) = delete;
    Service(Service&&) = default;
    virtual ~Service() = default;

    Service& operator=(const Service&) = delete;
    Service& operator=(Service&&) = default;

    //! Get the number of working threads
    size_t threads() const noexcept { return _threads.size(); }

    //! Is the service required strand to serialized handler execution?
    bool IsStrandRequired() const noexcept { return _strand_required; }
    //! Is the service started with polling loop mode?
    bool IsPolling() const noexcept { return _polling; }
    //! Is the service started?
    bool IsStarted() const noexcept { return _started; }

    //! Start the service
    /*!
        \param polling - Polling loop mode with idle handler call (default is false)
        \return 'true' if the service was successfully started, 'false' if the service failed to start
    */<commit_msg>Stick to io-service-per-thread design<commit_after>/*!
    \file service.h
    \brief Asio service definition
    \author <NAME>
    \date 16.12.2016
    \copyright MIT License
*/

#ifndef CPPSERVER_ASIO_SERVICE_H
#define CPPSERVER_ASIO_SERVICE_H

#include "asio.h"
#include "memory.h"

#include "threads/thread.h"

#include <atomic>
#include <cassert>
#include <memory>
#include <string>
#include <vector>

namespace CppServer {
namespace Asio {

//! Asio service
/*!
    Asio service is used to host all clients/servers based on Asio C++ library.
    It is implemented based on Asio C++ Library and use one or more threads to
    perform all asynchronous IO operations and communications.

    There are three ways to initialize Asio service:

    1) Service(threads, false) - initialize a new Asio service with io-service-
    per-thread design. In this case each Asio IO will be bounded to its own
    working thread and all handlers will be dispatched sequentially without
    strands making the code clean and easy to maintain.

    2) Service(threads, true) - initialize a new Asio service with thread-pool
    design. In this case single Asio IO will be bounded to all threads in pool,
    but strands will be required to serialize handler execution.

    3) Service(service, true | false) - initialize a new Asio service using the
    existing Asio IO service instance with required strands flag. Strands are
    required for serialized handler execution when single Asio IO service used
    in thread pool.

    Thread-safe.

    http://think-async.com
*/
class Service : public std::enable_shared_from_this<Service>
{
public:
    //! Initialize Asio service with single or multiple working threads
    /*!
        \param threads - Working threads count (default is 1)
        \param pool - Asio service thread pool flag (default is false)
    */
    explicit Service(int threads = 1, bool pool = false);
    //! Initialize Asio service manually with a given Asio IO service
    /*!
        \param service - Asio IO service
        \param strands - Asio IO service strands required flag (default is false)
    */
    explicit Service(std::shared_ptr<asio::io_service> service, bool strands = false);
    Service(const Service&) = delete;
    Service(Service&&) = default;
    virtual ~Service() = default;

    Service& operator=(const Service&) = delete;
    Service& operator=(Service&&) = default;

    //! Get the number of working threads
    size_t threads() const noexcept { return _threads.size(); }

    //! Is the service required strand to serialized handler execution?
    bool IsStrandRequired() const noexcept { return _strand_required; }
    //! Is the service started with polling loop mode?
    bool IsPolling() const noexcept { return _polling; }
    //! Is the service started?
    bool IsStarted() const noexcept { return _started; }

    //! Start the service
    /*!
        \param polling - Polling loop mode with idle handler call (default is false)
        \return 'true' if the service was successfully started, 'false' if the service failed to start
    */
{'fraction_non_alphanumeric': 0.07872098685278364, 'fraction_numerical': 0.004220094140561597, 'mean_word_length': 3.20040899795501, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4413923', 'n_tokens_mistral': 1677, 'n_tokens_neox': 1610, 'n_words': 733}