1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
| 用户: ///投资者结算结果确认响应 virtual void OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { CTraderSpi::OnRspSettlementInfoConfirm(pSettlementInfoConfirm, pRspInfo, nRequestID, bIsLast); SetEvent(g_hEvent); } 这里setEvent起什么作用 在这段代码中,`SetEvent(g_hEvent)` 的作用是 **触发一个事件对象(Event Object)**,通知其他等待该事件的线程可以继续执行。这是一种在多线程编程中常用的线程同步机制。
具体分析:
1. **上下文**: - 这是一个期货/证券交易API的回调函数(CTP接口),当结算单确认响应到达时被触发 - `g_hEvent` 是一个全局的事件对象句柄(HANDLE类型)
2. **典型使用场景**: - 主线程可能在调用查询结算单请求后,会调用`WaitForSingleObject(g_hEvent, INFINITE)`进入等待状态 - 当API收到响应并调用此回调时,`SetEvent`会唤醒正在等待的主线程 - 这样实现了异步操作的同步等待,使程序逻辑更清晰
3. **为什么需要**: - CTP API是异步通信模型 - 通过事件对象可以将异步回调转换为同步等待模式 - 确保结算单确认完成后再执行后续操作
4. **替代理解**: - 可以把它看作是一个"通知铃声"——当结算确认完成时"按响铃铛" - 其他等待中的线程听到铃声就知道可以继续工作了
这种模式在交易系统开发中非常常见,用于协调API的异步特性和业务逻辑需要的同步执行顺序。 用户: SetEvent(g_hEvent);在linux下如何实现 在 Linux 下,可以使用 POSIX 线程(pthread)的条件变量(condition variables)或事件机制(如 `eventfd`)来实现类似于 Windows 的 `SetEvent` 功能。以下是几种常见的实现方式:
---
### 方法 1:使用 `pthread` 条件变量 + 互斥锁 这是最接近 Windows 事件对象的实现方式,支持手动重置和自动重置事件。
#### 示例代码: ```c #include #include
typedef struct { pthread_mutex_t mutex; pthread_cond_t cond; bool is_set; } linux_event_t;
// 初始化事件 void linux_event_init(linux_event_t *event) { pthread_mutex_init(&event->mutex, NULL); pthread_cond_init(&event->cond, NULL); event->is_set = false; }
// 设置事件(类似 SetEvent) void linux_event_set(linux_event_t *event) { pthread_mutex_lock(&event->mutex); event->is_set = true; pthread_cond_signal(&event->cond); // 唤醒一个等待线程 pthread_mutex_unlock(&event->mutex); }
// 等待事件(类似 WaitForSingleObject) void linux_event_wait(linux_event_t *event) { pthread_mutex_lock(&event->mutex); while (!event->is_set) { pthread_cond_wait(&event->cond, &event->mutex); } event->is_set = false; // 自动重置(如需手动重置,移除此行) pthread_mutex_unlock(&event->mutex); }
// 销毁事件 void linux_event_destroy(linux_event_t *event) { pthread_mutex_destroy(&event->mutex); pthread_cond_destroy(&event->cond); } ```
#### 使用方式: ```c linux_event_t g_hEvent; linux_event_init(&g_hEvent);
// 线程1:等待事件 linux_event_wait(&g_hEvent);
// 线程2:触发事件 linux_event_set(&g_hEvent); ```
---
### 方法 2:使用 `eventfd`(轻量级事件通知) `eventfd` 是 Linux 特有的机制,适合与 I/O 多路复用(如 `epoll`)结合使用。
#### 示例代码: ```c #include #include
int g_hEvent; // 文件描述符
// 初始化事件 void linux_event_init() { g_hEvent = eventfd(0, EFD_SEMAPHORE); // EFD_SEMAPHORE 类似自动重置事件 }
// 设置事件(类似 SetEvent) void linux_event_set() { uint64_t val = 1; write(g_hEvent, &val, sizeof(val)); }
// 等待事件(类似 WaitForSingleObject) void linux_event_wait() { uint64_t val; read(g_hEvent, &val, sizeof(val)); }
// 销毁事件 void linux_event_destroy() { close(g_hEvent); } ```
#### 特点: - 适合与 `epoll`/`select` 集成。 - 跨线程/进程通知(通过 `fork` 共享文件描述符)。
---
### 方法 3:使用信号量(`semaphore`) 如果只需要简单的同步,可以使用 POSIX 信号量。
#### 示例代码: ```c #include
sem_t g_hEvent;
// 初始化事件 void linux_event_init() { sem_init(&g_hEvent, 0, 0); // 初始值为 0 }
// 设置事件(类似 SetEvent) void linux_event_set() { sem_post(&g_hEvent); }
// 等待事件(类似 WaitForSingleObject) void linux_event_wait() { sem_wait(&g_hEvent); }
// 销毁事件 void linux_event_destroy() { sem_destroy(&g_hEvent); } ```
---
### 选择建议: 1. **需要复杂同步逻辑**(如手动重置事件):用 **条件变量(方法1)**。 2. **需要与 I/O 多路复用集成**:用 **`eventfd`(方法2)**。 3. **简单线程同步**:用 **信号量(方法3)**。
根据你的具体场景选择最合适的实现方式。
|