mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-15 17:30:53 +08:00
167 lines
4.4 KiB
C++
167 lines
4.4 KiB
C++
#pragma once
|
||
#include "acl_cpp/acl_cpp_define.hpp"
|
||
#include "acl_cpp/ipc/ipc_service.hpp"
|
||
#if defined(_WIN32) || defined(_WIN64)
|
||
struct acl_pthread_mutex_t;
|
||
struct acl_pthread_cond_t;
|
||
#else
|
||
# include <pthread.h>
|
||
# ifndef acl_pthread_mutex_t
|
||
# define acl_pthread_mutex_t pthread_mutex_t
|
||
# endif
|
||
# ifndef acl_pthread_cond_t
|
||
# define acl_pthread_cond_t pthread_cond_t
|
||
# endif
|
||
#endif
|
||
|
||
namespace acl {
|
||
|
||
class ipc_client;
|
||
class rpc_client;
|
||
class rpc_service;
|
||
|
||
class rpc_request;
|
||
struct RPC_DAT
|
||
{
|
||
rpc_request* req;
|
||
void* ctx;
|
||
};
|
||
|
||
class ACL_CPP_API rpc_request : public ipc_request
|
||
{
|
||
public:
|
||
rpc_request(void);
|
||
virtual ~rpc_request(void);
|
||
|
||
protected:
|
||
friend class rpc_client;
|
||
friend class rpc_service;
|
||
|
||
/**
|
||
* 在主线程中被调用,子类必须实现此接口,
|
||
* 当子线程处理完请求任务后该接口将被调用,所以该类对象只能
|
||
* 是当本接口调用后才能被释放,禁止在调用本接口前释放本类对象
|
||
*/
|
||
virtual void rpc_onover(void) = 0;
|
||
|
||
/**
|
||
* 虚接口:当子线程调用本对象的 rpc_signal 时,在主线程中会
|
||
* 调用本接口,通知在任务未完成前(即调用 rpc_onover 前)收到
|
||
* 子线程运行的中间状态信息;内部自动支持套接口或 _WIN32 窗口
|
||
* 消息;应用场景,例如,对于 HTTP 下载应用,在子线程中可以
|
||
* 一边下载,一边向主线程发送(调用 rpc_signal 方法)下载进程,
|
||
* 则主线程会调用本类实例的此方法来处理此消息
|
||
*/
|
||
virtual void rpc_wakeup(void* ctx) { (void) ctx; }
|
||
|
||
protected:
|
||
/**
|
||
* 在子线程中被调用,子类必须实现此接口,用于处理具体任务
|
||
*/
|
||
virtual void rpc_run(void) = 0;
|
||
|
||
/**
|
||
* 在子线程中被调用,内部自动支持套接口或 _WIN32 窗口消息
|
||
* 子类实例的 rpc_run 方法中可以多次调用此方法向主线程的
|
||
* 本类实例发送消息,主线程中调用本对象 rpc_wakeup 方法
|
||
* @param ctx {void*} 传递的参数指针,一般应该是动态地址
|
||
* 比较好,这样可以避免同一个参数被重复覆盖的问题
|
||
*/
|
||
void rpc_signal(void* ctx);
|
||
|
||
/**
|
||
* 当子线程调用 rpc_signal 给主线程后,调用本方法可以等待
|
||
* 主线程发来下一步指令
|
||
* @param timeout {int} 等待超时时间(毫秒),当该值为 0 时
|
||
* 则采用非阻塞等待模式,当该值为 < 0 时,则采用完全阻塞
|
||
* 等待模式(即一直等到主线程发送 cond_signal 通知),当该
|
||
* 值 > 0 时,则等待的最大超时时间为 timeout 毫秒
|
||
* @return {bool} 返回 true 表示收到主线程发来的通知信号,
|
||
* 否则,需要调用 cond_wait_timeout 判断是否是超时引起的
|
||
*/
|
||
bool cond_wait(int timeout = -1);
|
||
|
||
/**
|
||
* 当 cond_wait 返回 false 时,应用应该调用本方法判断是否
|
||
* 是因为等待超时引起的
|
||
* @return {bool} 是否是等待超时
|
||
*/
|
||
bool cond_wait_timeout() const
|
||
{
|
||
return wait_timedout_;
|
||
}
|
||
|
||
/**
|
||
* 当子线程调用 cond_wait 时,在主线程中调用本方法通知子线程
|
||
* “醒来”
|
||
* @return {bool} 当有子线程调用 cond_wait 时本函数通知子线程
|
||
* “醒来”并且返回 true,否则返回 false
|
||
*/
|
||
bool cond_signal(void);
|
||
|
||
private:
|
||
RPC_DAT dat_;
|
||
ipc_client* ipc_;
|
||
int cond_count_;
|
||
acl_pthread_mutex_t* lock_;
|
||
acl_pthread_cond_t* cond_;
|
||
bool wait_timedout_;
|
||
|
||
// 基类 ipc_request 虚函数,在子线程中被调用
|
||
virtual void run(ipc_client* ipc);
|
||
#if defined(_WIN32) || defined(_WIN64)
|
||
/**
|
||
* 虚接口,子类实现此类用于处理具体的任务,该接口适用
|
||
* 于采用 _WIN32 消息的模式
|
||
* @param hWnd {HWND} WIN2 窗口句柄
|
||
*/
|
||
virtual void run(HWND hWnd);
|
||
#endif
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
class aio_socket_stream;
|
||
|
||
class ACL_CPP_API rpc_service : public ipc_service
|
||
{
|
||
public:
|
||
/**
|
||
* 构造函数
|
||
* @param nthread {int} 如果该值 > 1 则内部自动采用线程池,否则
|
||
* 则是一个请求一个线程
|
||
* @param ipc_keep {bool} 内部 IPC 消息流是否保持长连接,保持长
|
||
* 连接有助于提高消息传递的效率
|
||
*/
|
||
rpc_service(int nthread, bool ipc_keep = true);
|
||
|
||
~rpc_service(void) {}
|
||
|
||
/**
|
||
* 主线程中运行:将请求任务放入子线程池的任务请求队列中,当线程池
|
||
* 中的一个子线程接收到该任务后便调用 rpc_request::rpc_run 方法调
|
||
* 用子类的方法,当任务处理完毕后给主线程发消息,在主线程中再调用
|
||
* rpc_request::rpc_callback
|
||
* @param req {rpc_request*} rpc_request 子类实例,非空
|
||
*/
|
||
void rpc_fork(rpc_request* req);
|
||
|
||
private:
|
||
// 基类虚函数:主线程对象接收到子线程消息的
|
||
// ipc 连接请求时的回调函数
|
||
virtual void on_accept(aio_socket_stream* client);
|
||
|
||
#if defined(_WIN32) || defined(_WIN64)
|
||
/**
|
||
* 基类虚函数,当收到来自于子线程的 win32 消息时的回调函数
|
||
* @param hWnd {HWND} 窗口句柄
|
||
* @param msg {UINT} 用户自定义消息号
|
||
* @param wParam {WPARAM} 参数
|
||
* @param lParam {LPARAM} 参数
|
||
*/
|
||
virtual void win32_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
#endif
|
||
};
|
||
|
||
} // namespace acl
|