acl/lib_fiber/cpp/include/fiber/fiber.hpp

323 lines
5.7 KiB
C++
Raw Normal View History

2017-09-22 12:27:21 +08:00
#pragma once
#include <stddef.h>
#include "fiber_cpp_define.hpp"
2017-09-22 12:27:21 +08:00
struct ACL_FIBER;
namespace acl {
typedef enum
{
FIBER_EVENT_T_KERNEL,
FIBER_EVENT_T_POLL,
FIBER_EVENT_T_SELECT,
FIBER_EVENT_T_IOCP,
FIBER_EVENT_T_WMSG,
} fiber_event_t;
2017-09-22 12:27:21 +08:00
/**
2018-01-06 23:18:40 +08:00
* Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳в<EFBFBD>ʵ<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
class FIBER_CPP_API fiber
2017-09-22 12:27:21 +08:00
{
public:
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param running {bool} <EFBFBD><EFBFBD>Ϊ true ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>ǰЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѣ<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ACL_FIBER <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>󶨣<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> start <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>; <EFBFBD><EFBFBD>Ϊ false ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> start <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
fiber(bool running = false);
virtual ~fiber(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> running Ϊ false ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* Э<EFBFBD>̣<EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD> run <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> running Ϊ true ʱ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> start <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param stack_size {size_t} <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>С
2017-09-22 12:27:21 +08:00
*/
void start(size_t stack_size = 320000);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>ڱ<EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ô˺<EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>
* @return {bool} <EFBFBD><EFBFBD><EFBFBD><EFBFBD> false <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD>˳<EFBFBD>
2017-09-22 12:27:21 +08:00
*/
bool kill(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>жϵ<EFBFBD>ǰЭ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD>˳<EFBFBD>
* @return {bool} <EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD>˳<EFBFBD>
2017-09-22 12:27:21 +08:00
*/
bool killed(void) const;
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>жϵ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> killed <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
* killed <EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> acl::fiber <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD>Ҹ<EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>
* Ҳ<EFBFBD>п<EFBFBD><EFBFBD>ܱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𣬶<EFBFBD> self_killed <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ acl::fiber <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ
* <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Э<EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @return {bool}
*/
static bool self_killed(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID <EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @return {unsigned int}
*/
unsigned int get_id(void) const;
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID <EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @return {unsigned int}
*/
static unsigned int self(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD>ϵͳ API <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* return {int}
*/
int get_errno(void) const;
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰЭ<EFBFBD>̵Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @param errnum {int}
*/
void set_errno(int errnum);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĵ<EFBFBD><EFBFBD>ȹ<EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
static void schedule(fiber_event_t type = FIBER_EVENT_T_KERNEL);
2017-09-22 12:27:21 +08:00
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>жϵ<EFBFBD>ǰ<EFBFBD>߳<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD>״̬
2017-09-22 12:27:21 +08:00
* @return {bool}
*/
static bool scheduled(void);
/**
2018-01-06 23:18:40 +08:00
* ֹͣЭ<EFBFBD>̵<EFBFBD><EFBFBD>ȹ<EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
static void schedule_stop(void);
public:
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Э<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>) <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
static void yield(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰЭ<EFBFBD>̣<EFBFBD>ִ<EFBFBD>еȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
static void switch_to_next(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @param f {fiber&}
*/
static void ready(fiber& f);
/**
2018-01-06 23:18:40 +08:00
* ʹ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param milliseconds {unsigned int} ָ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ߵĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return {unsigned int} <EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD><EFBFBD>ٴα<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѻ<EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
static unsigned int delay(unsigned int milliseconds);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô˺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰ<EFBFBD>߳<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>Ҫ hook ϵͳ API<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ȱʡ
* <EFBFBD><EFBFBD> hook ϵͳ API
2017-09-22 12:27:21 +08:00
* @param on {bool}
*/
static void hook_api(bool on);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @return {int}
*/
static int get_sys_errno(void);
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @param errnum {int}
*/
static void set_sys_errno(int errnum);
public:
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD> C <EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD>Э<EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
* @return {ACL_FIBER* }
*/
ACL_FIBER* get_fiber(void) const;
protected:
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> start <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>̺󣬱<EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD>Ӷ<EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еIJ<EFBFBD><EFBFBD><EFBFBD>
* running Ϊ true <EFBFBD><EFBFBD><EFBFBD><EFBFBD> start <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
virtual void run(void);
private:
ACL_FIBER* f_;
static void fiber_callback(ACL_FIBER* f, void* ctx);
};
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
class FIBER_CPP_API fiber_timer
2017-09-22 12:27:21 +08:00
{
public:
fiber_timer(void);
virtual ~fiber_timer(void) {}
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Э<EFBFBD>̶<EFBFBD>ʱ<EFBFBD><EFBFBD>
* @param milliseconds {unsigned int} <EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* @param stack_size {size_t} Э<EFBFBD>̵<EFBFBD>ջ<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>С
2017-09-22 12:27:21 +08:00
*/
void start(unsigned int milliseconds, size_t stack_size = 320000);
protected:
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ָô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
virtual void run(void) = 0;
private:
ACL_FIBER* f_;
static void timer_callback(ACL_FIBER* f, void* ctx);
};
/**
2018-01-06 23:18:40 +08:00
* <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
2017-09-22 12:27:21 +08:00
*/
template <typename T>
class fiber_trigger : public fiber
{
public:
fiber_trigger(timer_trigger<T>& timer)
: delay_(100)
, stop_(false)
, timer_(timer)
{
}
virtual ~fiber_trigger(void) {}
void add(T* o)
{
mbox_.push(o);
}
void del(T* o)
{
timer_.del(o);
}
timer_trigger<T>& get_trigger(void)
{
return timer_;
}
// @override
void run(void)
{
while (!stop_) {
T* o = mbox_.pop(delay_);
if (o)
timer_.add(o);
long long next = timer_.trigger();
long long curr = get_curr_stamp();
if (next == -1)
delay_ = 100;
else {
delay_ = next - curr;
if (delay_ <= 0)
delay_ = 1;
}
}
}
private:
long long delay_;
bool stop_;
timer_trigger<T>& timer_;
mbox<T> mbox_;
};
} // namespace acl
#if defined(__GNUC__) && (__GNUC__ > 6 ||(__GNUC__ == 6 && __GNUC_MINOR__ >= 0))
# ifndef ACL_USE_CPP11
# define ACL_USE_CPP11
# endif
#endif
#ifdef ACL_USE_CPP11
#include <functional>
namespace acl
{
class FIBER_CPP_API go_fiber
2017-09-22 12:27:21 +08:00
{
public:
go_fiber(void) {}
go_fiber(size_t stack_size) : stack_size_(stack_size) {}
void operator=(std::function<void()> fn);
private:
size_t stack_size_ = 320000;
};
} // namespace acl
#define go acl::go_fiber()=
#define go_stack(size) acl::go_fiber(size)=
/**
* static void fiber1(void)
* {
* printf("fiber: %d\r\n", acl::fiber::self());
* }
*
* static void fiber2(acl::string& buf)
* {
* printf("in fiber: %d, buf: %s\r\n", acl::fiber::self(), buf.c_str());
* buf = "world";
* }
*
* static void fiber3(const acl::string& buf)
* {
* printf("in fiber: %d, buf: %s\r\n", acl::fiber::self(), buf.c_str());
* }
*
* static test(void)
* {
* go fiber1;
*
* acl::string buf("hello");
*
* go[&] {
* fiber2(buf);
* };
*
* go[=] {
* fiber3(buf);
* };
*
* go[&] {
* fiber3(buf);
* };
* }
*/
#endif