Skip to content

Latest commit

 

History

History
2871 lines (1971 loc) · 44.9 KB

File metadata and controls

2871 lines (1971 loc) · 44.9 KB

cu0

Abstract

cu0 is a header-only common utilities library for software engineering.

Contents

About
Usage
Libraries
	Environment
		cu0::Environment
		cu0::EnvironmentVariableData
		cu0::EnvironmentVariable
	Platform
                    NOT_AN_X
	Process
		cu0::Executable
		cu0::Process
		cu0::Strand
	Time
		cu0::AsyncCoarseTimer
		cu0::BlockCoarseTimer

About

SEE: readme.md:Testing for information on building and testing.

SEE: readme.md:Features for a brief tour of features.

Usage

cu0 can be used as a library or as a set of libraries.

To use it as a library, include cu0/cu0.hxx header.

#include <cu0/cu0.hxx>

That will include all other libraries.

To use it as a set of libraries, include only required to use libraries.

#include <cu0/some_cu0_library.hxx>

That will include only specified libraries and their dependencies if any.

Libraries

Library Header Description
env cu0/env.hxx Process environment control
platform cu0/platform.hxx Platform-dependent helpers
proc cu0/proc.hxx Process management
time cu0/time.hxx Time-related functionality
cu0 cu0/cu0.hxx Contains all the other libraries

Environment


struct cu0::Environment


struct cu0::Environment;

The Environment struct provides a way to access the environment

NOTE: no instances of this struct can be created

NOTE: for a way to access the environment of execution

SEE: cu0::Environment::as()


public:
constexpr cu0::Environment() = delete;

no instances of this struct can be created.


#if __has_include(<unistd.h>)
public:
template <class Return>
[[nodiscard]]
constexpr static Return cu0::Environment::as() = delete;
#endif

accesses the environment of execution and returns it as the specified type

NOTE: this function is marked deleted to allow only usage of specializations

Template parameters

Return is the type that will be returned

Returns

environment as Return type


#if __has_include(<unistd.h>)
public:
template <>
[[nodiscard]]
std::map<std::string, std::string> cu0::Environment::as();
#endif

NOTE: specialization of cu0::Environment::as()

copies environment variables into std::map<std::string, std::string>

NOTE: the behaviour is undefined if environment changes during function execution

Returns

a map of the current environment variables in the form <key, value>


#if __has_include(<unistd.h>)
public:
template <>
[[nodiscard]]
std::vector<EnvironmentVariable> cu0::Environment::as();
#endif

NOTE: specialization of cu0::Environment::as()

copies environment variables into std::vector<EnvironmentVariable>

NOTE: the behaviour is undefined if environment changes during function execution

Returns

vector of the current environment variables


#if __has_include(<unistd.h>)
protected:
template <class Return>
[[nodiscard]]
constexpr static Return cu0::Environment::as(
    const std::function<void(
        Return&, 
        std::string&&, 
        std::string&&
    )>& insert
);
#endif

accesses the environment of execution and returns it as the specified type

Template parameters

Return is the type that will be returned

Parameters

insert is the function to insert key-value data

Return& param is the first parameter of the function into which key-value data needs to be inserted

std::string&& is the second parameter of the function representing key of the environment variable

std::string&& is the third parameter of the function representing value of the environment variable

Returns

environment as Return type


struct cu0::EnvironmentVariableData


struct cu0::EnvironmentVariableData;

The EnvironmentVariableData struct provides a way to represent environment variables in a memory


public:
std::string cu0::EnvironmentVariableData::key{};

key of the associated environment variable


public:
std::optional<std::string> cu0::EnvironmentVariableData::value{};

value of the associated environment variable


struct cu0::EnvironmentVariable


struct cu0::EnvironmentVariable;

The EnvironmentVariable struct provides a way to access environment variable values


#if !defined(NOT_AN_X)
public:
enum class cu0::EnvironmentVariable::SetError;
#endif

enum of possible errors during value setting


#if !defined(NOT_AN_X)
cu0::EnvironmentVariable::SetError::INVALID
#endif

data_.key is a string of length 0, or contains an '=' character


#if !defined(NOT_AN_X)
cu0::EnvironmentVariable::SetError::MEMORY
#endif

insufficient memory to add a new variable to the environment


public:
virtual constexpr
cu0::EnvironmentVariable::~EnvironmentVariable() = default;

destructor that may be used in inherited structs


public:
[[nodiscard]]
static constexpr cu0::EnvironmentVariable
cu0::EnvironmentVariable::unsynced(std::string key);

creates an instance without syncing with the environment

Parameters

key is the environment variable key

Returns

unsynced environment variable


public:
[[nodiscard]]
static constexpr cu0::EnvironmentVariable
cu0::EnvironmentVariable::unsynced(
    cu0::EnvironmentVariableData data
);

creates an instance without syncing with the environment

Parameters

data is the environment variable data, i.e. key and value

Returns

unsynced environment variable with the value cached from the data


public:
[[nodiscard]]
static cu0::EnvironmentVariable
cu0::EnvironmentVariable::synced(std::string key);

creates an instance syncing with the environment

Parameters

key is the environment variable key

Returns

synced environment variable


public:
[[nodiscard]]
constexpr const cu0::EnvironmentVariableData&
cu0::EnvironmentVariable::data() const;

accesses the data of this instance

SEE: cu0::EnvironmentVariable::data_

Returns

data as a const reference


public:
[[nodiscard]]
constexpr const std::string& cu0::EnvironmentVariable::key() const;

accesses the key of an associated environment variable

Returns

key as a const reference


public:
[[nodiscard]]
constexpr const std::optional<std::string>&
cu0::EnvironmentVariable::cached() const;

accesses the cached value of the associated environment variable

NOTE: the cached value may not represent the associated environment variable if it was modified after the construction of this instance and before a call to this function

Returns

cached value as a const reference


public:
const std::optional<std::string>& cu0::EnvironmentVariable::sync();

syncs cached value to the actual value of the associated environment variable

Returns

new cached value as a const reference


#if !defined(NOT_AN_X)
public:
std::variant<
    std::monostate, 
    cu0::EnvironmentVariable::SetError
> cu0::EnvironmentVariable::set(std::string value);
#endif

sets the value of the associated environment variable

Parameters

value is the value to be set

Returns

if no error was reported => std::monostate

else => error code

SEE: cu0::EnvironmentVariable::SetError


#if !defined(NOT_AN_X)
public:
std::variant<
    std::monostate, 
    cu0::EnvironmentVariable::SetError
> cu0::EnvironmentVariable::unset();
#endif

unsets the value of the associated environment variable

Returns

if no error was reported => std::monostate

else => error code

SEE: cu0::EnvironmentVariable::SetError


#if !defined(NOT_AN_X)
protected:
template <class ConvertTo>
static constexpr ConvertTo cu0::EnvironmentVariable::convert(
    const int& error_number
);
#endif

converts an error number (error code) to the ConvertTo type

Template parameters

ConvertTo is a struct conversion to which is needed

NOTE: ConvertTo may be one of { SetError, }

Parameters

error_number is the error number (error code)

Returns

converted value


protected:
constexpr cu0::EnvironmentVariable::EnvironmentVariable() = default;

constructs an instance without syncing with the environment

NOTE: does not access an actual environment variable value


protected:
EnvironmentVariableData cu0::EnvironmentVariable::data_{};

key-value data of the associated environment variable


Platform


NOT_AN_X


NOT_AN_X is defined if this platform was detected as not an x platform

EXAMPLE: linux

EXAMPLE: unix

#if !defined(__unix__)
#if defined(NOT_AN_X)
#warning NOT_AN_X has been aready defined somewhere else => not redefining it
#else
#define NOT_AN_X
#endif
#endif

Proc


struct cu0::Executable


struct cu0::Executable;

The Executable struct represents an executable stored in a filesystem with arguments (if any) inside an environment


std::filesystem::path cu0::Executable::binary{};

path to a binary


std::vector<std::string> cu0::Executable::arguments{};

argument vector


std::map<std::string, std::string> cu0::Executable::environment{};

environment in the form <key, value>


namespace cu0::util

[[nodiscard]]
cu0::Executable cu0::find_by(const std::string& name);

finds an executable by a name

NOTE: searches in order:

the current directory

the directories specified by the PATH environment variable

Parameters

name is the name of an executable

Returns

executable with empty arguments and an empty environment

NOTE: if multiple executables are present with the specified name => the first found executable is returned


[[nodiscard]]
cu0::Executable cu0::find_by(
    const std::string& name,
    const std::filesystem::path& directory
);

finds an executable by a name

Parameters

name is the name of an executable

directory is the directory where to look for an executable

Returns

executable with empty arguments and an empty environment


[[nodiscard]]
std::tuple<std::unique_ptr<std::unique_ptr<char[]>[]>, std::size_t> 
cu0::argv_of(const cu0::Executable& executable);

converts arguments of an executable to ptr<ptr<char[]>[]>

Parameters

executable is the executable, arguments of which will be converted

directory is the directory where to look for an executable

Returns

tuple containing a ptr to an array and the size of that array


[[nodiscard]]
std::tuple<std::unique_ptr<std::unique_ptr<char[]>[]>, std::size_t> 
cu0::envp_of(const cu0::Executable& executable);

converts environment of an executable to ptr<ptr<char[]>[]>

NOTE: in format of "key=value"

Parameters

executable is the executable, environment of which will be converted

Returns

tuple containing a ptr to an array and the size of that array


struct cu0::Process


#if __has_include(<unistd.h>)
public:
enum struct cu0::Process::CreateError;
#endif

enum of possible errors for cu0::Process::create() and cu0::Process::create_pipeless() functions


cu0::Process::CreateError::AGAIN = EAGAIN,

SEE: EAGAIN


cu0::Process::CreateError::NOMEM = ENOMEM,

SEE: ENOMEM


cu0::Process::CreateError::INVAL = EINVAL,

SEE: EINVAL


cu0::Process::CreateError::MFILE = EMFILE,

SEE: EMFILE


cu0::Process::CreateError::NFILE = ENFILE,

SEE: ENFILE


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
enum struct cu0::Process::WaitError;
#endif

enum of possible errors for cu0::Process::wait_cautious() function

cu0::Process::WaitError::CHILD = ECHILD,

SEE: ECHILD


cu0::Process::WaitError::INVAL = EINVAL,

SEE: EINVAL


cu0::Process::WaitError::INTR = EINTR,

SEE: EINTR


#if __has_include(<unistd.h>)
public:
enum struct cu0::Process::WriteError;
#endif

enum of possible errors for cu0::Process::stdin_cautious() function

cu0::Process::WriteError::AGAIN = EAGAIN,

SEE: EAGAIN


#if EWOULDBLOCK != EAGAIN
cu0::Process::WriteError::WOULDBLOCK = EWOULDBLOCK,
#endif

SEE: EWOULDBLOCK


cu0::Process::WriteError::BADF = EBADF,

SEE: EBADF


cu0::Process::WriteError::DESTADDRREQ = EDESTADDRREQ,

SEE: EDESTADDRREQ


cu0::Process::WriteError::DQUOT = EDQUOT,

SEE: EDQUOT


cu0::Process::WriteError::FAULT = EFAULT,

SEE: EFAULT


cu0::Process::WriteError::FBIG = EFBIG,

SEE: EFBIG


cu0::Process::WriteError::INTR = EINTR,

SEE: EINTR


cu0::Process::WriteError::INVAL = EINVAL,

SEE: EINVAL


cu0::Process::WriteError::IO = EIO,

SEE: EIO


cu0::Process::WriteError::NOSPC = ENOSPC,

SEE: ENOSPC


cu0::Process::WriteError::PERM = EPERM,

SEE: EPERM


cu0::Process::WriteError::PIPE = EPIPE,

SEE: EPIPE


#if __has_include(<unistd.h>)
public:
enum struct cu0::Process::ReadError;
#endif

enum of possible errors for cu0::Process::stdout_cautious() and cu0::Process::stderr_cautious() functions


cu0::Process::ReadError::AGAIN = EAGAIN,

SEE: EAGAIN


cu0::Process::ReadError::BADF = EBADF,

SEE: EBADF


cu0::Process::ReadError::BADMSG = EBADMSG,

SEE: EBADMSG


cu0::Process::ReadError::INTR = EINTR,

SEE: EINTR


cu0::Process::ReadError::INVAL = EINVAL,

SEE: EINVAL


cu0::Process::ReadError::IO = EIO,

SEE: EIO


cu0::Process::ReadError::ISDIR = EISDIR,

SEE: EISDIR


cu0::Process::ReadError::OVERFLOW = EOVERFLOW,

SEE: EOVERFLOW


#if EWOULDBLOCK != EAGAIN
cu0::Process::ReadError::WOULDBLOCK = EWOULDBLOCK,
#endif

SEE: EWOULDBLOCK


cu0::Process::ReadError::CONNRESET = ECONNRESET,

SEE: ECONNRESET


cu0::Process::ReadError::NOTCONN = ENOTCONN,

SEE: ENOTCONN


cu0::Process::ReadError::TIMEDOUT = ETIMEDOUT,

SEE: ETIMEDOUT


cu0::Process::ReadError::NOBUFS = ENOBUFS,

SEE: ENOBUFS


cu0::Process::ReadError::NOMEM = ENOMEM,

SEE: ENOMEM


cu0::Process::ReadError::NXIO = ENXIO,

SEE: ENXIO


#if __has_include(<signal.h>)
public:
enum struct cu0::Process::SignalError;
#endif

enum of possible errors for cu0::Process::signal_cautious() function


cu0::Process::SignalError::INVAL = EINVAL,

SEE: EINVAL


cu0::Process::SignalError::PERM = EPERM,

SEE: EPERM


cu0::Process::SignalError::SRCH = ESRCH,

SEE: ESRCH


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
static cu0::Process cu0::Process::current();
#endif

constructs an instance using the current process in which this function is called

NOTE: for the returned current process cu0::Process::stdin(), cu0::Process::stdout(), cu0::Process::stderr() and their corresponding cautious member functions are not supported yet

SEE: implementation details of cu0::Process::current()

Returns

current process


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
static std::variant<cu0::Process, cu0::Process::CreateError>
cu0::Process::create(const cu0::Executable& executable);
#endif

creates a process using the specified executable

Parameters

executable is the excutable to be run by the process

Returns

if no error was reported => created process

else => error code


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
static std::variant<cu0::Process, cu0::Process::CreateError>
cu0::Process::create_pipeless(const cu0::Executable& executable);
#endif

creates a process using the specified executable without pipes

Parameters

executable is the excutable to be run by the process

Returns

if no error was reported => created process

else => error code


public:
virtual cu0::Process::~Process();

destructs an instance


public:
constexpr cu0::Process(const cu0::Process& other) = delete;

public:
constexpr cu0::Process& cu0::Process::operator =(
    const cu0::Process& other
) = delete;

public:
constexpr cu0::Process(cu0::Process&& other);

moves process resources to this process

Parameters

other is the process for which resources need to be moved


public:
constexpr cu0::Process& cu0::Process::operator =(cu0::Process&& other);

moves process resources to this process

Parameters

other is the process for which resources need to be moved

Returns

this process as a mutable reference


public:
[[nodiscard]]
constexpr const unsigned& cu0::Process::pid() const;

accesses process identifier value

Returns

process identifier as a const reference


public:
[[nodiscard]]
constexpr std::optional<int> cu0::Process::stdin_pipe() const;

accesses stdin pipe file descriptor

Returns

if stdin pipe file descriptor is valid => its value

else => empty optional


public:
[[nodiscard]]
constexpr std::optional<int> cu0::Process::stdout_pipe() const;

accesses stdout pipe file descriptor

Returns

if stdout pipe file descriptor is valid => its value

else => empty optional


public:
[[nodiscard]]
constexpr std::optional<int> cu0::Process::stderr_pipe() const;

accesses stderr pipe file descriptor

Returns

if stderr pipe file descriptor is valid => its value

else => empty optional


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
void cu0::Process::wait();
#endif

waits for the process to exit or to be terminated or to be stopped


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
[[nodiscard]]
std::variant<std::monostate, cu0::Process::WaitError>
cu0::Process::wait_cautious();
#endif

waits for the process to exit or to be terminated or to be stopped

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
[[nodiscard]]
constexpr const std::optional<int>& cu0::Process::exit_code() const;
#endif

accesses exit status code

NOTE: exit status code will be empty if the process hasn't exited normally

SEE: cu0::Process::wait()

Returns

exit status code as a const reference


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
[[nodiscard]]
constexpr const std::optional<int>& cu0::Process::termination_code() const;
#endif

accesses termination signal code

NOTE: termination signal code will be empty if the process hasn't been terminated

SEE: cu0::Process::wait()

Returns

termination signal code as a const reference


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
public:
[[nodiscard]]
constexpr const std::optional<int>& cu0::Process::stop_code() const;
#endif

accesses stop signal code

NOTE: stop signal code will be empty if the process hasn't been stopped

SEE: cu0::Process::wait()

Returns

stop signal code as a const reference


#if __has_include(<unistd.h>)
public:
void cu0::Process::stdin(const std::string& input) const;
#endif

passes the specified input to the stdin

Parameters

input is the input value


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
std::tuple<
    std::variant<std::monostate, cu0::Process::WriteError>, 
    std::size_t
> cu0::Process::stdin_cautious(const std::string& input) const;
#endif

passes the specified input to the stdin

Parameters

input is the input value

Returns

result of cu0::Process::write_into()

SEE: cu0::Process::write_into()


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
std::string cu0::stdout() const;
#endif

returns the value of the stdout

Returns

string containing stdout value


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
std::tuple<
    std::variant<std::monostate, cu0::Process::ReadError>, 
    std::string
> cu0::Process::stdout_cautious() const;
#endif

returns the value of the stdout

Returns

result of cu0::Process::read_from()

SEE: cu0::Process::read_from()


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
std::string cu0::stderr() const;
#endif

returns the value of the stderr

Returns

string containing stderr value


#if __has_include(<unistd.h>)
public:
[[nodiscard]]
std::tuple<
    std::variant<std::monostate, cu0::Process::ReadError>, 
    std::string
> cu0::Process::stderr_cautious() const;
#endif

returns the value of the stderr

Returns

result of cu0::Process::read_from()

SEE: cu0::Process::read_from()


#if __has_include(<signal.h>)
public:
void cu0::Process::signal(const int& code) const;
#endif

sends the specified code as a signal to this process

Parameters

code is the signal to be sent


#if __has_include(<signal.h>)
public:
[[nodiscard]]
std::variant<std::monostate, cu0::Process::SignalError>
cu0::Process::signal_cautious(const int& code) const;
#endif

sends the specified code as a signal to this process

Parameters

code is the signal to be sent

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<unistd.h>)
protected:
template <std::size_t BUFFER_SIZE, class Return>
static Return cu0::Process::write_into(
    const int& pipe,
    const std::string& input
);
#endif

writes the specified input into the specified pipe

Template parameters

BUFFER_SIZE is the buffer size for writing into the pipe

Return is the type to be returned by this function

Parameters

pipe is the pipe to write into

input is the data to write

Returns

if Return == std::tuple<
    std::variant<std::monostate, cu0::Process::WriteError>,
    std::size_t
> =>
    tuple containing
        variant of
            if no error was reported => std::monostate
            else => error code
        number of bytes written
            if no error was reported =>
                equal to input size
            else =>
                equal to the number of bytes that had already been
                written before an error was reported
if Return == void => nothing

#if __has_include(<unistd.h>)
protected:
template <std::size_t BUFFER_SIZE, class Return>
[[nodiscard]]
static Return cu0::Process::read_from(const int& pipe);
#endif

reads from the specified pipe

Template parameters

BUFFER_SIZE is the buffer size for reading from the pipe

Return is the type to be returned by this function

Parameters

pipe is the pipe to read from

Returns

if Return == std::tuple<
    std::variant<std::monostate, cu0::Process::ReadError>,
    std::string
> =>
    tuple containing
        variant of
            if no error was reported => std::monostate
            else => error code
        data that have been read
            if no error was reported => fully received
            else =>
                partially and contains data that had already been
                read before an error was reported
if Return == std::string => data that have been read as std::string

#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
protected:
template <class Return>
Return cu0::Process::wait_exit_loop();
#endif

loop to wait for process exit

Template parameters

Return is the type to be returned by this function

Parameters

pipe is the pipe to read from

Returns

if Return == std::variant<std::monostate, cu0::Process::WaitError> =>
    if no error was reported => std::monostate
    else =>
        error code of the first encountered error
if Return == void => no errors are returned and handled

protected:
constexpr cu0::Process::Process() = default;

constructs an instance with default values


protected:
constexpr void cu0::Process::swap(cu0::Process&& other);

swaps two processes

Parameters

other is the process to swap this process with


protected:
unsigned cu0::Process::pid_ = 0;

process identifier


protected:
int cu0::Process::stdin_pipe_ = -1;

stdin file descriptor


protected:
int cu0::Process::stdout_pipe_ = -1;

stdout file descriptor


protected:
int cu0::Process::stderr_pipe_ = -1;

stderr file descriptor


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
protected:
std::optional<int> cu0::Process::exit_code_ = {};
#endif

if waited => actual exit status code value if present

SEE: cu0::Process::wait()

else => empty exit status code value


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
protected:
std::optional<int> cu0::Process::termination_code_ = {};
#endif

if waited => actual termination signal code value if present

SEE: cu0::Process::wait()

else => empty termination signal code value


#if __has_include(<sys/types.h>) && __has_include(<sys/wait.h>)
protected:
std::optional<int> cu0::Process::stop_code_ = {};
#endif

if waited => actual stop signal code value if present

SEE: cu0::Process::wait()

else => empty stop signal code value


struct cu0::Strand


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::Policy;
#endif

available policies


cu0::Strand::Policy::PTHREAD_OTHER = SCHED_OTHER,

SEE: SCHED_OTHER


cu0::Strand::Policy::PTHREAD_FIFO = SCHED_FIFO,

SEE: SCHED_FIFO


cu0::Strand::Policy::PTHREAD_RR = SCHED_RR,

SEE: SCHED_RR


#if __has_include(<pthread.h>)
public:
using cu0::Strand::PriorityType = std::remove_reference_t<
    decltype(std::declval<sched_param>().sched_priority)
>;
#endif

underlying priority type


#if __has_include(<pthread.h>)
public:
struct cu0::Strand::Scheduling;
#endif

scheduling data representation

public:
cu0::Strand::Policy 
cu0::Strand::Scheduling::policy = cu0::Strand::Policy::PTHREAD_OTHER;

policy

public:
cu0::Strand::PriorityType cu0::Strand::Scheduling::priority{};

NOTE: policy-specific when it is modified use

sched_get_priority_min(static_cast<int>(Policy))

and

sched_get_priority_max(static_cast<int>(Policy))

to get minimal and maximal values for the specified policy


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::Stage;
#endif

stage of a strand


cu0::Strand::Stage::NOT_LAUNCHED = SCHED_OTHER,

before cu0::Strand::run()


cu0::Strand::Stage::LAUNCHED = SCHED_FIFO,

after cu0::Strand::run() but before cu0::Strand::join()


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::ResourceError;
#endif

errors related to resource management of a strand


cu0::Strand::ResourceError::PTHREAD_NOMEM = ENOMEM,

no memory


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::GetPriorityError;
#endif

errors related to retrieval of a priority value


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::SetPriorityError;
#endif

errors related to modification of a priority value


cu0::Strand::SetPriorityError::PTHREAD_NOTSUP = ENOTSUP,

unsupported priority or policy was specified


cu0::Strand::SetPriorityError::PTHREAD_INVAL = EINVAL,

invalid priority or policy was specified


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::GetPolicyError;
#endif

errors related to retrieval of a policy value


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::SetPolicyError;
#endif

errors related to modification of a policy value


cu0::Strand::SetPolicyError::PTHREAD_NOTSUP = ENOTSUP,

unsupported policy was specified


cu0::Strand::SetPolicyError::PTHREAD_INVAL = EINVAL,

invalid policy was specified


cu0::Strand::SetPolicyError::PTHREAD_PERM = EPERM,

current privileges are not enough


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::GetDetachedError;
#endif

errors related to retrieval of a status of the detached state


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::SetDetachedError;
#endif

errors related to modification of a status of the detached state


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::GetStackSizeError;
#endif

errors related to retrieval of a stack size


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::SetStackSizeError;
#endif

errors related to modification of a stack size


cu0::Strand::SetStackSizeError::PTHREAD_INVAL = EINVAL,

bad aligned or small or big size was specified


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::InitError;
#endif

errors related to initializtion of a strand and its parameters


cu0::Strand::InitError::PTHREAD_NOTSUP = ENOTSUP,

operation unsupported on the platform was requested

changing scheduling and/or priority will not make effect


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::RunError;
#endif

errors related to launching of a strand


cu0::Strand::RunError::PTHREAD_AGAIN = EAGAIN,

insufficient resources or limit


cu0::Strand::RunError::PTHREAD_PERM = EPERM,

no permission to apply strand parameters


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::JoinError;
#endif

errors related to joining to a strand


cu0::Strand::JoinError::PTHREAD_DEADLK = EDEADLK,

deadlock was detected


#if __has_include(<pthread.h>)
public:
enum struct cu0::Strand::SetDetachedError;
#endif

errors related to detaching of a strand


cu0::Strand::InitError::PTHREAD_INVAL = EINVAL,

strand is not detachable


public:
[[nodiscard]] static
#if __has_include(<pthread.h>)
std::variant<
    cu0::Strand, 
    cu0::Strand::ResourceError, 
    cu0::Strand::InitError
>
#else
std::variant<cu0::Strand>
#endif
cu0::Strand::create(std::function<void()> task);

creates a strand instance

Parameters

task is the task to be executed after launch

SEE: cu0::Strand::run()

Returns

if no error was reported => strand instance

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::PriorityType,
    cu0::Strand::GetPriorityError
> cu0::Strand::priority() const = delete;
#endif

gets a priority of this strand

NOTE: deleted | actual implementations are provided through specializations

Returns

if no error was reported => priority value

else => error code


#if __has_include(<pthread.h>)
public:
template <>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::PriorityType,
    cu0::Strand::GetPriorityError
> cu0::Strand::priority<cu0::Strand::Stage::NOT_LAUNCHED>() const;
#endif

gets a priority with which this strand will be launched

Returns

if no error was reported => priority value

else => error code


#if __has_include(<pthread.h>)
public:
template <>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::PriorityType,
    cu0::Strand::GetPriorityError
> cu0::Strand::priority<cu0::Strand::Stage::LAUNCHED>() const;
#endif

gets a priority with which this strand is running

Returns

if no error was reported => priority value

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPriorityError
> cu0::Strand::priority(
    const cu0::Strand::PriorityType& priority
) = delete;
#endif

sets a priority of this strand

NOTE: deleted | actual implementations are provided through specializations

Parameters

priority is the priority to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPriorityError
> cu0::Strand::priority<cu0::Strand::Stage::NOT_LAUNCHED>(
    const cu0::Strand::PriorityType& priority
);
#endif

sets a priority with which this strand will be launched

Parameters

priority is the priority to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPriorityError
> cu0::Strand::priority<cu0::Strand::Stage::LAUNCHED>(
    const cu0::Strand::PriorityType& priority
);
#endif

sets a priority with which this strand will continue to run

Parameters

priority is the priority to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::Scheduling,
    cu0::Strand::GetPolicyError,
    cu0::Strand::GetPriorityError
> cu0::Strand::scheduling() const = delete;
#endif

gets scheduling parameters of this strand

NOTE: deleted | actual implementations are provided through specializations

Returns

if no error was reported => scheduling parameters

else => error code


#if __has_include(<pthread.h>)
public:
template <>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::Scheduling,
    cu0::Strand::GetPolicyError,
    cu0::Strand::GetPriorityError
> cu0::Strand::scheduling<cu0::Strand::Stage::NOT_LAUNCHED>() const;
#endif

gets scheduling parameters with which this strand will be launched

Returns

if no error was reported => scheduling parameters

else => error code


#if __has_include(<pthread.h>)
public:
template <>
[[nodiscard]]
constexpr std::variant<
    cu0::Strand::Scheduling,
    cu0::Strand::GetPolicyError,
    cu0::Strand::GetPriorityError
> cu0::Strand::scheduling<cu0::Strand::Stage::LAUNCHED>() const;
#endif

gets scheduling parameters with which this strand is running

NOTE: cu0::Strand::GetPriorityError is not used by this implementation

Returns

if no error was reported => scheduling parameters

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPolicyError,
    cu0::Strand::SetPriorityError
> cu0::Strand::scheduling(
    const Scheduling& scheduling
) = delete;
#endif

sets scheduling parameters of this strand

NOTE: deleted | actual implementations are provided through specializations

Parameters

scheduling is the scheduling parameters to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPolicyError,
    cu0::Strand::SetPriorityError
> cu0::Strand::scheduling<cu0::Strand::Stage::NOT_LAUNCHED>(
    const Scheduling& scheduling
);
#endif

sets scheduling parameters with which this strand will be launched

Parameters

scheduling is the scheduling parameters to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetPolicyError,
    cu0::Strand::SetPriorityError
> cu0::Strand::scheduling<cu0::Strand::Stage::LAUNCHED>(
    const Scheduling& scheduling
);
#endif

sets scheduling parameters with which this strand will continue to run

NOTE: cu0::Strand::SetPriorityError is not used by this implementation

Parameters

scheduling is the scheduling parameters to be set

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
[[nodiscard]]
constexpr std::variant<
    bool,
    cu0::Strand::GetDetachedError
> cu0::Strand::detached() const = delete;
#endif

gets a status of the detached state of this strand

NOTE: deleted | actual implementations are provided through specializations

Returns

if no error was reported => status of the detached state

else => error code


#if __has_include(<pthread.h>)
public:
template <>
[[nodiscard]]
constexpr std::variant<
    bool,
    cu0::Strand::GetDetachedError
> cu0::Strand::detached<cu0::Strand::Stage::NOT_LAUNCHED>() const;
#endif

gets a status of the detached state with which this strand will be

Returns

if no error was reported => status of the detached state

else => error code


#if __has_include(<pthread.h>)
public:
template <cu0::Strand::Stage stage>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetDetachedError
> cu0::Strand::detached(
    const bool detached
) = delete;
#endif

sets a status of the detached state of this strand

NOTE: deleted | actual implementations are provided through specializations

Parameters

detached is the flag specifying if this strand needs to be detached

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetDetachedError
> cu0::Strand::detached<cu0::Strand::Stage::NOT_LAUNCHED>(
    const bool detached
);
#endif

sets a status of the detached state with which this strand will be launched

Parameters

detached is the flag specifying if this strand needs to be detached

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
template <cu0::Strand::Stage stage>
[[nodiscard]]
constexpr std::variant<
    std::size_t,
    cu0::Strand::GetStackSizeError
> cu0::Strand::stack_size() const = delete;
#endif

gets stack size to be allocated for this strand

NOTE: deleted | actual implementations are provided through specializations

Returns

if no error was reported => stack size in bytes

else => error code


#if __has_include(<pthread.h>)
template <>
[[nodiscard]]
constexpr std::variant<
    std::size_t,
    cu0::Strand::GetStackSizeError
> stack_size<cu0::Strand::Stage::NOT_LAUNCHED>() const;
#endif

gets stack size to be allocated for this strand before launch

Returns

if no error was reported => stack size in bytes

else => error code


#if __has_include(<pthread.h>)
template <cu0::Strand::Stage stage>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetStackSizeError,
    cu0::Strand::ResourceError
> cu0::Strand::allocate_stack(const std::size_t stack_size) = delete;
#endif

allocates stack for this strand

NOTE: deleted | actual implementations are provided through specializations

Parameters

stack_size is the size of a stack to be allocated in bytes

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
#if __has_include(<stdlib.h>) && __has_include(<unistd.h>)
template <>
constexpr std::variant<
    std::monostate,
    cu0::Strand::SetStackSizeError,
    cu0::Strand::ResourceError
> cu0::Strand::allocate_stack<cu0::Strand::Stage::NOT_LAUNCHED>(
    const std::size_t stack_size
);
#endif
#endif

allocates stack for this strand before launch

NOTE: allocated stack should be deallocated

SEE: cu0::Strand::deallocate_stack()

Parameters

stack_size is the size of a stack to be allocated in bytes

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
template <cu0::Strand::Stage stage>
constexpr std::variant<std::monostate> 
cu0::Strand::deallocate_stack() = delete;
#endif

deallocates stack from this strand

NOTE: deleted | actual implementations are provided through specializations

Returns

if no error was reported => std::monostate


#if __has_include(<pthread.h>)
#if __has_include(<stdlib.h>) && __has_include(<unistd.h>)
template <>
constexpr std::variant<std::monostate> 
cu0::Strand::deallocate_stack<cu0::Strand::Stage::NOT_LAUNCHED>();
#endif
#endif

deallocates stack from this strand

NOTE: use after cu0::Strand::join() if cu0::Strand::allocate_stack(std::size_t) was called

Returns

if no error was reported => std::monostate


#if __has_include(<pthread.h>)
public:
std::variant<
    std::monostate,
    cu0::Strand::RunError,
    cu0::Strand::ResourceError
>
#else
std::variant<std::monostate>
#endif
cu0::Strand::run();

runs a task specified by this->task_ in a new thread, i.e. launches this strand

Returns

if no error was reported => std::monostate

else => error code


#if __has_include(<pthread.h>)
public:
std::variant<
    std::monostate,
    cu0::Strand::JoinError
>
#else
std::variant<std::monostate>
#endif
cu0::Strand::join();

joins to this strand, i.e. waits for the strand to exit

Returns

if no error was reported => std::monostate

else => error code


public:
#if __has_include(<pthread.h>)
  constexpr std::variant<std::monostate, cu0::Strand::DetachError>
#else
  std::variant<std::monostate>
#endif
cu0::Strand::detach();

detaches this strand

Returns

if no error was reported => std::monostate

else => error code


protected:
#if __has_include(<pthread.h>)
constexpr
#else
inline
#endif
cu0::Strand::Strand() = default;

default ctor


#if __has_include(<pthread.h>)
protected:
static void* task(void* args);
#endif

calls reinterpret_cast<Strand const *>(args)->task_ task

NOTE: used as a helper to launch a strand

Parameters

args is the pointer to the instance of this type

Returns

nullptr


protected:
std::function<void()> cu0::Strand::task_{};

task to be executed after launch


#if __has_include(<pthread.h>)
protected:
pthread_attr_t cu0::Strand::attr_{};
#endif

internal representation of parameters with which a strand is launched

SEE: cu0::Strand::Scheduling


protected:
#if __has_include(<pthread.h>)
pthread_t
#else
std::thread
#endif
cu0::Strand::thread_{};

thread implementation


Time


cu0::AsyncCoarseTimer


template <class Rep, class Period>
struct cu0::AsyncCoarseTimer;

struct representing asynchronous coarse timer which can be launched

Template parameters

Rep is the type representing number of ticks

EXAMPLE: float

Period is the type representing tick period

EXAMPLE: std::milli is the period of one millisecond

EXAMPLE: std::ratio<1, 1> is the period of one second


public:
explicit constexpr 
cu0::AsyncCoarseTimer<Rep, Period>::AsyncCoarseTimer(
    std::chrono::duration<Rep, Period> duration
);

constructs an instance with the specified duration

Parameters

duration is the duration which should be waited after launch


public:
constexpr void cu0::AsyncCoarseTimer<Rep, Period>::launch();

launches the timer

SEE: cu0::AsyncCoarseTimer<Rep, Period>::wait()


public:
constexpr void cu0::AsyncCoarseTimer<Rep, Period>::wait() const;

waits for the timer to be up if it is not already


protected:
std::chrono::time_point<
    std::chrono::steady_clock,
    std::chrono::duration<Rep, Period>
> cu0::AsyncCoarseTimer<Rep, Period>::launch_time_;

time point when timer was launched


cu0::BlockCoarseTimer


template <class Rep, class Period>
struct cu0::BlockCoarseTimer;

struct representing blocking coarse timer which can be launched

Template parameters

Rep is the type representing number of ticks

EXAMPLE: float

Period is the type representing tick period

EXAMPLE: std::milli is the period of one millisecond

EXAMPLE: std::ratio<1, 1> is the period of one second


public:
explicit constexpr 
cu0::BlockCoarseTimer<Rep, Period>::BlockCoarseTimer(
    std::chrono::duration<Rep, Period> duration
);

constructs an instance with the specified duration

Parameters

duration is the duration which should be waited after launch


public:
constexpr void cu0::BlockCoarseTimer<Rep, Period>::launch();

launches the timer and sleeps the specified duration

SEE: cu0::BlockCoarseTimer<Rep, Period>::duration_


protected:
std::chrono::duration<Rep, Period> 
cu0::BlockCoarseTimer<Rep, Period>::duration_;

duration to sleep and block after launch