summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstorri <storri@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-01-12 00:02:29 +0000
committerstorri <storri@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-01-12 00:02:29 +0000
commit5a041dae3274f8dabf8f00a2210a6a24a4cebdfc (patch)
tree4dfcbb1415950d7ef38b49fb9548b7ebac9c7e49
parentcebd47ea20aabcf5858d9d8d8e5792486e7f7ba4 (diff)
downloadATCD-5a041dae3274f8dabf8f00a2210a6a24a4cebdfc.tar.gz
Updates for directory structure
-rw-r--r--ace/ATM/ATM_Acceptor.cpp~309
-rw-r--r--ace/ATM/ATM_Acceptor.h14
-rw-r--r--ace/ATM/ATM_Addr.cpp6
-rw-r--r--ace/ATM/ATM_Addr.h4
-rw-r--r--ace/ATM/ATM_Connector.cpp8
-rw-r--r--ace/ATM/ATM_Connector.h6
-rw-r--r--ace/ATM/ATM_Params.h6
-rw-r--r--ace/ATM/ATM_Stream.cpp4
-rw-r--r--ace/ATM/ATM_Stream.h10
-rw-r--r--ace/ATM/Makefile4
-rw-r--r--ace/Connection/Acceptor.cpp1184
-rw-r--r--ace/Connection/Acceptor.h567
-rw-r--r--ace/Connection/Asynch_Acceptor.cpp496
-rw-r--r--ace/Connection/Asynch_Acceptor.h202
-rw-r--r--ace/Connection/Asynch_IO.cpp1276
-rw-r--r--ace/Connection/Asynch_IO.h1441
-rw-r--r--ace/Connection/Asynch_IO_Impl.cpp108
-rw-r--r--ace/Connection/Asynch_IO_Impl.h684
-rw-r--r--ace/Connection/Asynch_IO_Impl.i87
-rw-r--r--ace/Connection/Caching_Strategies_T.cpp57
-rw-r--r--ace/Connection/Caching_Strategies_T.h537
-rw-r--r--ace/Connection/Caching_Strategies_T.i448
-rw-r--r--ace/Connection/Connector.cpp952
-rw-r--r--ace/Connection/Connector.h531
-rw-r--r--ace/Connection/LOCK_SOCK_Acceptor.cpp33
-rw-r--r--ace/Connection/LOCK_SOCK_Acceptor.h62
-rw-r--r--ace/Connection/POSIX_Asynch_IO.cpp2912
-rw-r--r--ace/Connection/POSIX_Asynch_IO.h1732
-rw-r--r--ace/Connection/POSIX_Asynch_IO.i2
-rw-r--r--ace/Connection/Sock_Connect.cpp1127
-rw-r--r--ace/Connection/Sock_Connect.h89
-rw-r--r--ace/Connection/Sock_Connect.i1
-rw-r--r--ace/Connection/Strategies_T.cpp1230
-rw-r--r--ace/Connection/Strategies_T.h971
-rw-r--r--ace/Connection/Strategies_T.i439
-rw-r--r--ace/Connection/WIN32_Asynch_IO.cpp2320
-rw-r--r--ace/Connection/WIN32_Asynch_IO.h1628
-rw-r--r--ace/Demux/Event_Handler.cpp254
-rw-r--r--ace/Demux/Event_Handler.h216
-rw-r--r--ace/Demux/Event_Handler.i10
-rw-r--r--ace/Demux/Event_Handler_T.cpp63
-rw-r--r--ace/Demux/Event_Handler_T.h187
-rw-r--r--ace/Demux/Event_Handler_T.i185
-rw-r--r--ace/Demux/FlReactor.cpp331
-rw-r--r--ace/Demux/FlReactor.h111
-rw-r--r--ace/Demux/FlReactor.i2
-rw-r--r--ace/Demux/Makefile (renamed from ace/ATM/Makefile~)64
-rw-r--r--ace/Demux/POSIX_Proactor.cpp1935
-rw-r--r--ace/Demux/POSIX_Proactor.h589
-rw-r--r--ace/Demux/POSIX_Proactor.i20
-rw-r--r--ace/Demux/Priority_Reactor.cpp171
-rw-r--r--ace/Demux/Priority_Reactor.h89
-rw-r--r--ace/Demux/Proactor.cpp1110
-rw-r--r--ace/Demux/Proactor.h601
-rw-r--r--ace/Demux/Proactor.i75
-rw-r--r--ace/Demux/Proactor_Impl.h236
-rw-r--r--ace/Demux/QtReactor.cpp435
-rw-r--r--ace/Demux/QtReactor.h153
-rw-r--r--ace/Demux/Reactor.cpp285
-rw-r--r--ace/Demux/Reactor.h674
-rw-r--r--ace/Demux/Reactor.i676
-rw-r--r--ace/Demux/Reactor_Impl.h561
-rw-r--r--ace/Demux/Reactor_Notification_Strategy.cpp33
-rw-r--r--ace/Demux/Reactor_Notification_Strategy.h58
-rw-r--r--ace/Demux/Reactor_Notification_Strategy.inl13
-rw-r--r--ace/Demux/SUN_Proactor.cpp370
-rw-r--r--ace/Demux/SUN_Proactor.h121
-rw-r--r--ace/Demux/SUN_Proactor.i8
-rw-r--r--ace/Demux/Select_Reactor.cpp44
-rw-r--r--ace/Demux/Select_Reactor.h68
-rw-r--r--ace/Demux/Select_Reactor_Base.cpp1135
-rw-r--r--ace/Demux/Select_Reactor_Base.h537
-rw-r--r--ace/Demux/Select_Reactor_Base.i93
-rw-r--r--ace/Demux/Select_Reactor_T.cpp1427
-rw-r--r--ace/Demux/Select_Reactor_T.h770
-rw-r--r--ace/Demux/Select_Reactor_T.i241
-rw-r--r--ace/Demux/TkReactor.cpp439
-rw-r--r--ace/Demux/TkReactor.h130
-rw-r--r--ace/Demux/WFMO_Reactor.cpp2563
-rw-r--r--ace/Demux/WFMO_Reactor.h1324
-rw-r--r--ace/Demux/WFMO_Reactor.i1131
-rw-r--r--ace/Demux/WIN32_Proactor.cpp736
-rw-r--r--ace/Demux/WIN32_Proactor.h296
-rw-r--r--ace/IPC/Addr.cpp65
-rw-r--r--ace/IPC/Addr.h106
-rw-r--r--ace/IPC/Addr.i69
-rw-r--r--ace/IPC/DEV.cpp37
-rw-r--r--ace/IPC/DEV.h74
-rw-r--r--ace/IPC/DEV.i15
-rw-r--r--ace/IPC/DEV_Addr.cpp81
-rw-r--r--ace/IPC/DEV_Addr.h84
-rw-r--r--ace/IPC/DEV_Addr.i64
-rw-r--r--ace/IPC/DEV_Connector.cpp43
-rw-r--r--ace/IPC/DEV_Connector.h104
-rw-r--r--ace/IPC/DEV_Connector.i30
-rw-r--r--ace/IPC/DEV_IO.cpp126
-rw-r--r--ace/IPC/DEV_IO.h134
-rw-r--r--ace/IPC/DEV_IO.i101
-rw-r--r--ace/IPC/FIFO.cpp74
-rw-r--r--ace/IPC/FIFO.h79
-rw-r--r--ace/IPC/FIFO.i20
-rw-r--r--ace/IPC/FIFO_Recv.cpp82
-rw-r--r--ace/IPC/FIFO_Recv.h76
-rw-r--r--ace/IPC/FIFO_Recv.i18
-rw-r--r--ace/IPC/FIFO_Recv_Msg.cpp61
-rw-r--r--ace/IPC/FIFO_Recv_Msg.h81
-rw-r--r--ace/IPC/FIFO_Recv_Msg.i76
-rw-r--r--ace/IPC/FIFO_Send.cpp53
-rw-r--r--ace/IPC/FIFO_Send.h66
-rw-r--r--ace/IPC/FIFO_Send.i18
-rw-r--r--ace/IPC/FIFO_Send_Msg.cpp70
-rw-r--r--ace/IPC/FIFO_Send_Msg.h80
-rw-r--r--ace/IPC/FIFO_Send_Msg.i48
-rw-r--r--ace/IPC/FILE.cpp151
-rw-r--r--ace/IPC/FILE.h140
-rw-r--r--ace/IPC/FILE.i16
-rw-r--r--ace/IPC/FILE_Addr.cpp110
-rw-r--r--ace/IPC/FILE_Addr.h85
-rw-r--r--ace/IPC/FILE_Addr.i43
-rw-r--r--ace/IPC/FILE_Connector.cpp84
-rw-r--r--ace/IPC/FILE_Connector.h110
-rw-r--r--ace/IPC/FILE_Connector.i33
-rw-r--r--ace/IPC/FILE_IO.cpp133
-rw-r--r--ace/IPC/FILE_IO.h160
-rw-r--r--ace/IPC/FILE_IO.i145
-rw-r--r--ace/IPC/INET_Addr.cpp935
-rw-r--r--ace/IPC/INET_Addr.h330
-rw-r--r--ace/IPC/INET_Addr.i159
-rw-r--r--ace/IPC/IOStream.cpp658
-rw-r--r--ace/IPC/IOStream.h513
-rw-r--r--ace/IPC/IOStream_T.cpp210
-rw-r--r--ace/IPC/IOStream_T.h289
-rw-r--r--ace/IPC/IOStream_T.i160
-rw-r--r--ace/IPC/IO_SAP.cpp142
-rw-r--r--ace/IPC/IO_SAP.h90
-rw-r--r--ace/IPC/IO_SAP.i39
-rw-r--r--ace/IPC/Pipe.cpp235
-rw-r--r--ace/IPC/Pipe.h86
-rw-r--r--ace/IPC/Pipe.i25
-rw-r--r--ace/IPC/SPIPE.cpp63
-rw-r--r--ace/IPC/SPIPE.h100
-rw-r--r--ace/IPC/SPIPE.i16
-rw-r--r--ace/IPC/SPIPE_Acceptor.cpp271
-rw-r--r--ace/IPC/SPIPE_Acceptor.h101
-rw-r--r--ace/IPC/SPIPE_Addr.cpp142
-rw-r--r--ace/IPC/SPIPE_Addr.h113
-rw-r--r--ace/IPC/SPIPE_Addr.i74
-rw-r--r--ace/IPC/SPIPE_Connector.cpp76
-rw-r--r--ace/IPC/SPIPE_Connector.h105
-rw-r--r--ace/IPC/SPIPE_Connector.i13
-rw-r--r--ace/IPC/SPIPE_Stream.cpp98
-rw-r--r--ace/IPC/SPIPE_Stream.h147
-rw-r--r--ace/IPC/SPIPE_Stream.i198
-rw-r--r--ace/IPC/SV_Message.cpp19
-rw-r--r--ace/IPC/SV_Message.h56
-rw-r--r--ace/IPC/SV_Message.i31
-rw-r--r--ace/IPC/SV_Message_Queue.cpp39
-rw-r--r--ace/IPC/SV_Message_Queue.h95
-rw-r--r--ace/IPC/SV_Message_Queue.i78
-rw-r--r--ace/IPC/SV_Semaphore_Complex.cpp252
-rw-r--r--ace/IPC/SV_Semaphore_Complex.h155
-rw-r--r--ace/IPC/SV_Semaphore_Complex.i83
-rw-r--r--ace/IPC/SV_Semaphore_Simple.cpp202
-rw-r--r--ace/IPC/SV_Semaphore_Simple.h158
-rw-r--r--ace/IPC/SV_Semaphore_Simple.i106
-rw-r--r--ace/IPC/SV_Shared_Memory.cpp83
-rw-r--r--ace/IPC/SV_Shared_Memory.h112
-rw-r--r--ace/IPC/SV_Shared_Memory.i114
-rw-r--r--ace/IPC/Signal.cpp861
-rw-r--r--ace/IPC/Signal.h511
-rw-r--r--ace/IPC/Signal.i306
-rw-r--r--ace/IPC/TLI.cpp195
-rw-r--r--ace/IPC/TLI.h107
-rw-r--r--ace/IPC/TLI.i46
-rw-r--r--ace/IPC/TLI_Acceptor.cpp546
-rw-r--r--ace/IPC/TLI_Acceptor.h118
-rw-r--r--ace/IPC/TLI_Connector.cpp247
-rw-r--r--ace/IPC/TLI_Connector.h126
-rw-r--r--ace/IPC/TLI_Connector.i47
-rw-r--r--ace/IPC/TLI_Stream.cpp110
-rw-r--r--ace/IPC/TLI_Stream.h129
-rw-r--r--ace/IPC/TLI_Stream.i149
-rw-r--r--ace/IPC/TTY_IO.cpp436
-rw-r--r--ace/IPC/TTY_IO.h84
-rw-r--r--ace/IPC/UNIX_Addr.cpp114
-rw-r--r--ace/IPC/UNIX_Addr.h99
-rw-r--r--ace/IPC/UNIX_Addr.i67
-rw-r--r--ace/IPC/UPIPE_Acceptor.cpp122
-rw-r--r--ace/IPC/UPIPE_Acceptor.h94
-rw-r--r--ace/IPC/UPIPE_Acceptor.i11
-rw-r--r--ace/IPC/UPIPE_Addr.h45
-rw-r--r--ace/IPC/UPIPE_Connector.cpp91
-rw-r--r--ace/IPC/UPIPE_Connector.h112
-rw-r--r--ace/IPC/UPIPE_Connector.i33
-rw-r--r--ace/IPC/UPIPE_Stream.cpp227
-rw-r--r--ace/IPC/UPIPE_Stream.h137
-rw-r--r--ace/IPC/UPIPE_Stream.i12
-rw-r--r--ace/IPC/XTI_ATM_Mcast.cpp66
-rw-r--r--ace/IPC/XTI_ATM_Mcast.h129
-rw-r--r--ace/IPC/XTI_ATM_Mcast.i62
-rw-r--r--ace/Logging/Dump.cpp136
-rw-r--r--ace/Logging/Dump.h168
-rw-r--r--ace/Logging/Dump_T.cpp41
-rw-r--r--ace/Logging/Dump_T.h78
-rw-r--r--ace/Logging/Log_Msg.cpp2109
-rw-r--r--ace/Logging/Log_Msg.h665
-rw-r--r--ace/Logging/Log_Msg_Backend.cpp9
-rw-r--r--ace/Logging/Log_Msg_Backend.h64
-rw-r--r--ace/Logging/Log_Msg_Callback.cpp9
-rw-r--r--ace/Logging/Log_Msg_Callback.h65
-rw-r--r--ace/Logging/Log_Msg_IPC.cpp72
-rw-r--r--ace/Logging/Log_Msg_IPC.h63
-rw-r--r--ace/Logging/Log_Msg_NT_Event_Log.cpp143
-rw-r--r--ace/Logging/Log_Msg_NT_Event_Log.h68
-rw-r--r--ace/Logging/Log_Msg_UNIX_Syslog.cpp186
-rw-r--r--ace/Logging/Log_Msg_UNIX_Syslog.h72
-rw-r--r--ace/Logging/Log_Priority.h76
-rw-r--r--ace/Logging/Log_Record.cpp299
-rw-r--r--ace/Logging/Log_Record.h202
-rw-r--r--ace/Logging/Log_Record.i107
-rw-r--r--ace/Logging/Logging_Strategy.cpp495
-rw-r--r--ace/Logging/Logging_Strategy.h169
-rw-r--r--ace/Logging/Trace.cpp126
-rw-r--r--ace/Logging/Trace.h86
-rw-r--r--ace/Memory/Based_Pointer_Repository.cpp123
-rw-r--r--ace/Memory/Based_Pointer_Repository.h70
-rw-r--r--ace/Memory/Based_Pointer_T.cpp114
-rw-r--r--ace/Memory/Based_Pointer_T.h198
-rw-r--r--ace/Memory/Based_Pointer_T.i136
-rw-r--r--ace/Memory/Bound_Ptr.h300
-rw-r--r--ace/Memory/Bound_Ptr.i481
-rw-r--r--ace/Memory/MEM_Acceptor.cpp239
-rw-r--r--ace/Memory/MEM_Acceptor.h173
-rw-r--r--ace/Memory/MEM_Acceptor.i89
-rw-r--r--ace/Memory/MEM_Addr.cpp153
-rw-r--r--ace/Memory/MEM_Addr.h153
-rw-r--r--ace/Memory/MEM_Addr.i117
-rw-r--r--ace/Memory/MEM_Connector.cpp143
-rw-r--r--ace/Memory/MEM_Connector.h125
-rw-r--r--ace/Memory/MEM_Connector.i24
-rw-r--r--ace/Memory/MEM_IO.cpp536
-rw-r--r--ace/Memory/MEM_IO.h301
-rw-r--r--ace/Memory/MEM_IO.i230
-rw-r--r--ace/Memory/MEM_SAP.cpp88
-rw-r--r--ace/Memory/MEM_SAP.h161
-rw-r--r--ace/Memory/MEM_SAP.i67
-rw-r--r--ace/Memory/MEM_Stream.cpp41
-rw-r--r--ace/Memory/MEM_Stream.h142
-rw-r--r--ace/Memory/MEM_Stream.i176
-rw-r--r--ace/Memory/Malloc.cpp161
-rw-r--r--ace/Memory/Malloc.h414
-rw-r--r--ace/Memory/Malloc.i21
-rw-r--r--ace/Memory/Malloc_Allocator.cpp165
-rw-r--r--ace/Memory/Malloc_Allocator.h161
-rw-r--r--ace/Memory/Malloc_Allocator.i239
-rw-r--r--ace/Memory/Malloc_Base.h156
-rw-r--r--ace/Memory/Malloc_Instantiations.cpp33
-rw-r--r--ace/Memory/Malloc_T.cpp943
-rw-r--r--ace/Memory/Malloc_T.h730
-rw-r--r--ace/Memory/Malloc_T.i296
-rw-r--r--ace/Memory/Mem_Map.cpp386
-rw-r--r--ace/Memory/Mem_Map.h214
-rw-r--r--ace/Memory/Mem_Map.i251
-rw-r--r--ace/Memory/Memory_Pool.cpp1324
-rw-r--r--ace/Memory/Memory_Pool.h756
-rw-r--r--ace/Memory/Memory_Pool.i244
-rw-r--r--ace/Memory/Obchunk.cpp30
-rw-r--r--ace/Memory/Obchunk.h72
-rw-r--r--ace/Memory/Obchunk.i9
-rw-r--r--ace/Memory/Obstack.cpp11
-rw-r--r--ace/Memory/Obstack.h28
-rw-r--r--ace/Memory/Obstack_T.cpp163
-rw-r--r--ace/Memory/Obstack_T.h114
-rw-r--r--ace/Memory/Obstack_T.i33
-rw-r--r--ace/Memory/PI_Malloc.cpp176
-rw-r--r--ace/Memory/PI_Malloc.h213
-rw-r--r--ace/Memory/PI_Malloc.i25
-rw-r--r--ace/Memory/Read_Buffer.cpp162
-rw-r--r--ace/Memory/Read_Buffer.h114
-rw-r--r--ace/Memory/Read_Buffer.i28
-rw-r--r--ace/Memory/Shared_Memory.cpp9
-rw-r--r--ace/Memory/Shared_Memory.h51
-rw-r--r--ace/Memory/Shared_Memory_MM.cpp52
-rw-r--r--ace/Memory/Shared_Memory_MM.h116
-rw-r--r--ace/Memory/Shared_Memory_MM.i89
-rw-r--r--ace/Memory/Shared_Memory_SV.cpp30
-rw-r--r--ace/Memory/Shared_Memory_SV.h97
-rw-r--r--ace/Memory/Shared_Memory_SV.i73
-rw-r--r--ace/Other/Local_Name_Space.cpp225
-rw-r--r--ace/Other/Local_Name_Space.h130
-rw-r--r--ace/Other/Local_Name_Space_T.cpp926
-rw-r--r--ace/Other/Local_Name_Space_T.h266
-rw-r--r--ace/Other/Msg_WFMO_Reactor.cpp90
-rw-r--r--ace/Other/Msg_WFMO_Reactor.h114
-rw-r--r--ace/Other/Msg_WFMO_Reactor.i30
-rw-r--r--ace/Other/Name_Proxy.cpp201
-rw-r--r--ace/Other/Name_Proxy.h91
-rw-r--r--ace/Other/Name_Request_Reply.cpp556
-rw-r--r--ace/Other/Name_Request_Reply.h260
-rw-r--r--ace/Other/Name_Space.cpp61
-rw-r--r--ace/Other/Name_Space.h161
-rw-r--r--ace/Other/Naming_Context.cpp693
-rw-r--r--ace/Other/Naming_Context.h364
-rw-r--r--ace/Other/Registry_Name_Space.cpp277
-rw-r--r--ace/Other/Registry_Name_Space.h134
-rw-r--r--ace/Other/Remote_Name_Space.cpp351
-rw-r--r--ace/Other/Remote_Name_Space.h140
-rw-r--r--ace/Other/TP_Reactor.cpp829
-rw-r--r--ace/Other/TP_Reactor.h357
-rw-r--r--ace/Other/TP_Reactor.i93
-rw-r--r--ace/Other/XtReactor.cpp450
-rw-r--r--ace/Other/XtReactor.h136
-rw-r--r--ace/Sockets/IPC_SAP.cpp182
-rw-r--r--ace/Sockets/IPC_SAP.h84
-rw-r--r--ace/Sockets/IPC_SAP.i37
-rw-r--r--ace/Sockets/LSOCK.cpp172
-rw-r--r--ace/Sockets/LSOCK.h77
-rw-r--r--ace/Sockets/LSOCK.i40
-rw-r--r--ace/Sockets/LSOCK_Acceptor.cpp135
-rw-r--r--ace/Sockets/LSOCK_Acceptor.h90
-rw-r--r--ace/Sockets/LSOCK_CODgram.cpp56
-rw-r--r--ace/Sockets/LSOCK_CODgram.h73
-rw-r--r--ace/Sockets/LSOCK_CODgram.i27
-rw-r--r--ace/Sockets/LSOCK_Connector.cpp58
-rw-r--r--ace/Sockets/LSOCK_Connector.h108
-rw-r--r--ace/Sockets/LSOCK_Connector.i29
-rw-r--r--ace/Sockets/LSOCK_Dgram.cpp66
-rw-r--r--ace/Sockets/LSOCK_Dgram.h70
-rw-r--r--ace/Sockets/LSOCK_Dgram.i20
-rw-r--r--ace/Sockets/LSOCK_Stream.cpp132
-rw-r--r--ace/Sockets/LSOCK_Stream.h77
-rw-r--r--ace/Sockets/LSOCK_Stream.i25
-rw-r--r--ace/Sockets/SOCK.cpp182
-rw-r--r--ace/Sockets/SOCK.h120
-rw-r--r--ace/Sockets/SOCK.i34
-rw-r--r--ace/Sockets/SOCK_Acceptor.cpp398
-rw-r--r--ace/Sockets/SOCK_Acceptor.h171
-rw-r--r--ace/Sockets/SOCK_Acceptor.i12
-rw-r--r--ace/Sockets/SOCK_CODgram.cpp106
-rw-r--r--ace/Sockets/SOCK_CODgram.h70
-rw-r--r--ace/Sockets/SOCK_CODgram.i18
-rw-r--r--ace/Sockets/SOCK_Connector.cpp335
-rw-r--r--ace/Sockets/SOCK_Connector.h236
-rw-r--r--ace/Sockets/SOCK_Connector.i35
-rw-r--r--ace/Sockets/SOCK_Dgram.cpp513
-rw-r--r--ace/Sockets/SOCK_Dgram.h214
-rw-r--r--ace/Sockets/SOCK_Dgram.i158
-rw-r--r--ace/Sockets/SOCK_Dgram_Bcast.cpp333
-rw-r--r--ace/Sockets/SOCK_Dgram_Bcast.h133
-rw-r--r--ace/Sockets/SOCK_Dgram_Bcast.i34
-rw-r--r--ace/Sockets/SOCK_Dgram_Mcast.cpp414
-rw-r--r--ace/Sockets/SOCK_Dgram_Mcast.h193
-rw-r--r--ace/Sockets/SOCK_Dgram_Mcast.i78
-rw-r--r--ace/Sockets/SOCK_IO.cpp157
-rw-r--r--ace/Sockets/SOCK_IO.h143
-rw-r--r--ace/Sockets/SOCK_IO.i149
-rw-r--r--ace/Sockets/SOCK_Stream.cpp35
-rw-r--r--ace/Sockets/SOCK_Stream.h167
-rw-r--r--ace/Sockets/SOCK_Stream.i171
-rw-r--r--ace/Streams/CDR_Base.cpp585
-rw-r--r--ace/Streams/CDR_Base.h291
-rw-r--r--ace/Streams/CDR_Base.inl205
-rw-r--r--ace/Streams/CDR_Stream.cpp1433
-rw-r--r--ace/Streams/CDR_Stream.h1143
-rw-r--r--ace/Streams/CDR_Stream.i1493
365 files changed, 93656 insertions, 385 deletions
diff --git a/ace/ATM/ATM_Acceptor.cpp~ b/ace/ATM/ATM_Acceptor.cpp~
deleted file mode 100644
index eb4c5d6c874..00000000000
--- a/ace/ATM/ATM_Acceptor.cpp~
+++ /dev/null
@@ -1,309 +0,0 @@
-// $Id$
-
-#include "ATM_Acceptor.h"
-
-ACE_RCSID(ace, ATM_Acceptor, "$Id$")
-
-#if defined (ACE_HAS_ATM)
-
-#if defined (ACE_HAS_LINUX_ATM)
-#include "linux/atmdev.h"
-#endif /* ACE_HAS_LINUX_ATM */
-
-#if !defined (__ACE_INLINE__)
-#include "ATM_Acceptor.i"
-#endif /* __ACE_INLINE__ */
-
-// Put the actual definitions of the ACE_ATM_Request and
-// ACE_ATM_Request_Queue classes here to hide them from clients...
-
-ACE_ALLOC_HOOK_DEFINE(ACE_ATM_Acceptor)
-
-void
-ACE_ATM_Acceptor::dump (void) const
-{
- ACE_TRACE ("ACE_ATM_Acceptor::dump");
-}
-
-ACE_ATM_Acceptor::ACE_ATM_Acceptor (void)
-{
- ACE_TRACE ("ACE_ATM_Acceptor::ACE_ATM_Acceptor");
-}
-
-ACE_ATM_Acceptor::~ACE_ATM_Acceptor (void)
-{
- ACE_TRACE ("ACE_ATM_Acceptor::~ACE_ATM_Acceptor");
-}
-
-int
-ACE_ATM_Acceptor::get_local_addr( ACE_ATM_Addr &local_addr )
-{
- ACE_TRACE( "ACE_ATM_Acceptor::get_local_addr" );
-
-#if defined (ACE_HAS_FORE_ATM_WS2)
- unsigned long ret = 0;
- DWORD deviceID = 0;
- ATM_ADDRESS addr;
- struct sockaddr_atm *laddr;
-
- if ( ::WSAIoctl(( int )(( ACE_SOCK_Acceptor *)this ) -> get_handle(),
- SIO_GET_ATM_ADDRESS,
- (LPVOID) &deviceID,
- sizeof(DWORD),
- ( LPVOID )&addr,
- sizeof( ATM_ADDRESS ),
- &ret,
- NULL,
- NULL ) == SOCKET_ERROR ) {
- ACE_OS::printf( "ATM_Acceptor(get_local_addr): WSIoctl: %d\n",
- ::WSAGetLastError());
- return -1;
- }
-
- laddr = ( struct sockaddr_atm *)local_addr.get_addr();
- ACE_OS::memcpy(( void *)&( laddr -> satm_number ),
- ( void *)&addr,
- ATM_ADDR_SIZE - 1 );
-
- return 0;
-#elif defined (ACE_HAS_FORE_ATM_XTI)
- ACE_UNUSED_ARG( local_addr );
-
- return 0;
-#elif defined (ACE_HAS_LINUX_ATM)
- ATM_Addr *myaddr = (ATM_Addr *)local_addr.get_addr();
- int addrlen = sizeof(myaddr->sockaddratmsvc);
-
- if (ACE_OS::getsockname(acceptor_.get_handle(),
- (struct sockaddr *) &(myaddr->sockaddratmsvc),
- &addrlen) < 0) {
- ACE_DEBUG((LM_DEBUG,
- ACE_LIB_TEXT ("ATM_Acceptor(get_local_addr): ioctl: %d\n"),
- errno));
- return -1;
- }
-
- return (0);
-#else
- ACE_UNUSED_ARG( local_addr );
-
- return 0;
-#endif /* ACE_HAS_FORE_ATM_WS2 && ACE_HAS_FORE_ATM_XTI */
-}
-
-ACE_HANDLE
-ACE_ATM_Acceptor::open (const ACE_Addr &remote_sap,
- int backlog,
- ACE_ATM_Params params)
-{
- ACE_TRACE ("ACE_ATM_Acceptor::open");
-#if defined (ACE_HAS_FORE_ATM_XTI)
- ACE_HANDLE handle = acceptor_.open (remote_sap,
- params.get_reuse_addr(),
- params.get_oflag(),
- params.get_info(),
- backlog,
- params.get_device());
- return (handle == ACE_INVALID_HANDLE ? -1 : 0);
-#elif defined (ACE_HAS_FORE_ATM_WS2)
- struct sockaddr_atm local_atm_addr;
- ACE_HANDLE ret;
- DWORD flags = 0;
-
- /* Create a local endpoint of communication */
-
- // Only leaves can listen.
- flags = ACE_FLAG_MULTIPOINT_C_LEAF | ACE_FLAG_MULTIPOINT_D_LEAF;
-
- if ((ret = ACE_OS::socket (AF_ATM,
- SOCK_RAW,
- ATMPROTO_AAL5,
- NULL,
- 0,
- flags ))
- == ACE_INVALID_HANDLE) {
- ACE_OS::printf( "Acceptor(open): socket %d\n",
- ::WSAGetLastError());
- return (ret);
- }
-
- ((ACE_SOCK_Acceptor *)this) -> set_handle( ret );
-
- /* Set up the address information to become a server */
- ACE_OS::memset ((void *) &local_atm_addr, 0, sizeof local_atm_addr);
- local_atm_addr.satm_family = AF_ATM;
- local_atm_addr.satm_number.AddressType = SAP_FIELD_ANY_AESA_REST;
- local_atm_addr.satm_number.Addr[ ATM_ADDR_SIZE - 1 ]
- = (( ACE_ATM_Addr *)&remote_sap ) -> get_selector();
- local_atm_addr.satm_blli.Layer2Protocol = SAP_FIELD_ANY;
- local_atm_addr.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
- local_atm_addr.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
-
- /* Associate address with endpoint */
- if (ACE_OS::bind ((( ACE_SOCK_Acceptor *)this ) -> get_handle(),
- ACE_reinterpret_cast(struct sockaddr *, &local_atm_addr),
- sizeof local_atm_addr) == -1) {
- ACE_OS::printf( "Acceptor(open): bind %d\n", ::WSAGetLastError());
- return (ACE_INVALID_HANDLE);
- }
-
- /* Make endpoint listen for service requests */
- if (ACE_OS::listen ((( ACE_SOCK_Acceptor *)this ) -> get_handle(),
- backlog)
- == -1) {
- ACE_OS::printf( "Acceptor(open): listen %d\n", ::WSAGetLastError());
- return (ACE_INVALID_HANDLE);
- }
-
- return 0;
-#elif defined (ACE_HAS_LINUX_ATM)
- //we need to set the qos before binding to the socket
- //use remote_sap as local_sap
-
- ACE_ATM_Addr local_sap;
- ATM_Addr *local_sap_addr = (ATM_Addr*)local_sap.get_addr();
- ACE_ATM_QoS def_qos;
- ATM_QoS qos = def_qos.get_qos();
-
- ACE_HANDLE handle;
- if ((handle = ACE_OS::socket (params.get_protocol_family(),
- params.get_type(),
- params.get_protocol(),
- params.get_protocol_info(),
- params.get_sock_group(),
- params.get_flags()
- ))
- == ACE_INVALID_HANDLE) {
- ACE_DEBUG(LM_DEBUG,
- ACE_LIB_TEXT ("Acceptor(socket): socket %d\n"),
- errno);
- return (ACE_INVALID_HANDLE);
- }
-
- ((ACE_SOCK_Acceptor *)this) -> set_handle( handle );
- if (ACE_OS::setsockopt(handle,
- SOL_ATM,
- SO_ATMQOS,
- ACE_reinterpret_cast(char*, &qos),
- sizeof(qos)) < 0) {
- ACE_OS::printf("Acceptor(setsockopt): setsockopt:%d\n",
- errno);
- }
-
- struct atmif_sioc req;
- struct sockaddr_atmsvc aux_addr[1024];
-
- req.number = 0;
- req.arg = aux_addr;
- req.length = sizeof(aux_addr);
- if (ACE_OS::ioctl(handle,
- ATM_GETADDR,
- &req) < 0) {
- ACE_OS::perror( "Acceptor(setsockopt): ioctl:");
- }
- else {
- local_sap_addr->sockaddratmsvc = aux_addr[0];
- }
- local_sap.set_selector(((ACE_ATM_Addr*)&remote_sap)->get_selector());
-
- if (ACE_OS::bind (handle,
- ACE_reinterpret_cast(struct sockaddr *,
- &(local_sap_addr->sockaddratmsvc)),
- sizeof (local_sap_addr->sockaddratmsvc)
- ) == -1) {
- ACE_DEBUG(LM_DEBUG,
- ACE_LIB_TEXT ("Acceptor(open): bind %d\n"),
- errno);
- return -1;
- }
- // Make endpoint listen for service requests
- if (ACE_OS::listen (handle,
- backlog)
- == -1) {
- ACE_DEBUG(LM_DEBUG,
- ACE_LIB_TEXT ("Acceptor(listen): listen %d\n"),
- errno);
- return -1;
- }
-
- return 0;
-#else
- ACE_UNUSED_ARG (remote_sap);
- ACE_UNUSED_ARG (backlog);
- ACE_UNUSED_ARG (params);
-#endif /* ACE_HAS_FORE_ATM_XTI/ACE_HAS_FORE_ATM_WS2/ACE_HAS_LINUX_ATM */
-}
-
-int
-ACE_ATM_Acceptor::accept (ACE_ATM_Stream &new_sap,
- ACE_Addr *remote_addr,
- ACE_Time_Value *timeout,
- int restart,
- int reset_new_handle,
- ACE_ATM_Params params,
- ACE_ATM_QoS qos)
-{
- ACE_TRACE ("ACE_ATM_Acceptor::accept");
-#if defined (ACE_HAS_FORE_ATM_XTI)
- ATM_QoS optbuf = qos.get_qos();
-
- return (acceptor_.accept(new_sap.get_stream(),
- remote_addr,
- timeout,
- restart,
- reset_new_handle,
- params.get_rw_flag(),
- params.get_user_data(),
- &optbuf));
-#elif defined (ACE_HAS_FORE_ATM_WS2)
- ACE_HANDLE n_handle;
- ACE_HANDLE s_handle = (( ACE_SOCK_Acceptor *) this ) -> get_handle();
- struct sockaddr_atm *cli_addr
- = ( struct sockaddr_atm *)remote_addr -> get_addr();
- int caddr_len = sizeof( struct sockaddr_atm );
-
- do {
- n_handle = ACE_OS::accept(s_handle,
- ACE_reinterpret_cast(struct sockaddr *,
- cli_addr ),
- &caddr_len );
- } while ( n_handle == ACE_INVALID_HANDLE && errno == EINTR );
-
- (( ACE_ATM_Addr *)remote_addr ) -> set( cli_addr,
- (( ACE_ATM_Addr *)remote_addr ) -> get_selector());
- (( ACE_IPC_SAP *)&new_sap ) -> set_handle( n_handle );
-
- return 0;
-#elif defined (ACE_HAS_LINUX_ATM)
- ACE_UNUSED_ARG (params);
-
- ACE_HANDLE s_handle = (( ACE_SOCK_Acceptor *) this ) -> get_handle();
- struct atm_qos accept_qos = qos.get_qos();
-
- if (ACE_OS::setsockopt(s_handle,
- SOL_ATM,
- SO_ATMQOS,
- ACE_reinterpret_cast(char*,
- &accept_qos),
- sizeof(accept_qos)) < 0) {
- ACE_OS::printf("Acceptor(accept): error setting Qos");
- }
-
- return(acceptor_.accept(new_sap.get_stream(),
- remote_addr,
- timeout,
- restart,
- reset_new_handle));
-#else
- ACE_UNUSED_ARG(new_sap);
- ACE_UNUSED_ARG(remote_addr);
- ACE_UNUSED_ARG(timeout);
- ACE_UNUSED_ARG(restart);
- ACE_UNUSED_ARG(reset_new_handle);
- ACE_UNUSED_ARG(params);
- ACE_UNUSED_ARG(qos);
- return (0);
-#endif /* ACE_HAS_FORE_ATM_XTI */
-}
-
-#endif /* ACE_HAS_ATM */
diff --git a/ace/ATM/ATM_Acceptor.h b/ace/ATM/ATM_Acceptor.h
index 173be1ad532..8e89311e2bd 100644
--- a/ace/ATM/ATM_Acceptor.h
+++ b/ace/ATM/ATM_Acceptor.h
@@ -15,10 +15,10 @@
#define ACE_ATM_ACCEPTOR_H
#include "ace/pre.h"
-#include "ace/Time_Value.h"
-#include "ace/ATM_Stream.h"
-#include "ace/ATM_Params.h"
-#include "ace/ATM_QoS.h"
+#include "ace/Timer/Time_Value.h"
+#include "ace/ATM/ATM_Stream.h"
+#include "ace/ATM/ATM_Params.h"
+#include "ace/ATM/ATM_QoS.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
@@ -31,10 +31,10 @@
#endif /* ACE_HAS_LINUX_ATM */
#if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
-#include "SOCK_Acceptor.h"
+#include "ace/Sockets/SOCK_Acceptor.h"
typedef ACE_SOCK_Acceptor ATM_Acceptor;
#elif defined (ACE_HAS_FORE_ATM_XTI)
-#include "TLI_Acceptor.h"
+#include "ace/IPC/TLI_Acceptor.h"
typedef ACE_TLI_Acceptor ATM_Acceptor;
#endif // ACE_HAS_FORE_ATM_WS2 || ACE_HAS_LINUX_ATM
@@ -101,7 +101,7 @@ private:
};
#if defined (__ACE_INLINE__)
-#include "ace/ATM_Acceptor.i"
+#include "ace/ATM/ATM_Acceptor.i"
#endif /* __ACE_INLINE__ */
#endif /* ACE_HAS_ATM */
diff --git a/ace/ATM/ATM_Addr.cpp b/ace/ATM/ATM_Addr.cpp
index ed00d04dca3..1ec140c6d61 100644
--- a/ace/ATM/ATM_Addr.cpp
+++ b/ace/ATM/ATM_Addr.cpp
@@ -2,15 +2,15 @@
// Defines the Internet domain address family address format.
-#include "ace/ATM_Addr.h"
-#include "ace/Log_Msg.h"
+#include "ace/ATM/ATM_Addr.h"
+#include "ace/Logging/Log_Msg.h"
#if defined (ACE_HAS_FORE_ATM_WS2)
#include "forews2.h"
#endif /* ACE_HAS_FORE_ATM_WS2 */
#if !defined (__ACE_INLINE__)
-#include "ace/ATM_Addr.i"
+#include "ace/ATM/ATM_Addr.i"
#endif /* __ACE_INLINE__ */
ACE_RCSID(ace, ATM_Addr, "$Id$")
diff --git a/ace/ATM/ATM_Addr.h b/ace/ATM/ATM_Addr.h
index 85319006ba5..d61bee9ee54 100644
--- a/ace/ATM/ATM_Addr.h
+++ b/ace/ATM/ATM_Addr.h
@@ -13,7 +13,7 @@
#include "ace/pre.h"
#include "ace/ACE.h"
-#include "ace/Addr.h"
+#include "ace/IPC/Addr.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
@@ -172,7 +172,7 @@ private:
};
#if defined (__ACE_INLINE__)
-#include "ace/ATM_Addr.i"
+#include "ace/ATM/ATM_Addr.i"
#endif /* __ACE_INLINE__ */
#include "ace/post.h"
diff --git a/ace/ATM/ATM_Connector.cpp b/ace/ATM/ATM_Connector.cpp
index 29856669fb7..2e43da4f1e8 100644
--- a/ace/ATM/ATM_Connector.cpp
+++ b/ace/ATM/ATM_Connector.cpp
@@ -1,15 +1,15 @@
// ATM_Connector.cpp
// $Id$
-#include "ace/Handle_Set.h"
-#include "ace/ATM_Connector.h"
+#include "ace/OS/Handle_Set.h"
+#include "ace/ATM/ATM_Connector.h"
ACE_RCSID(ace, ATM_Connector, "$Id$")
#if defined (ACE_HAS_ATM)
#if !defined (__ACE_INLINE__)
-#include "ace/ATM_Connector.i"
+#include "ace/ATM/ATM_Connector.i"
#endif /* __ACE_INLINE__ */
ACE_ALLOC_HOOK_DEFINE(ACE_ATM_Connector)
@@ -29,7 +29,7 @@ ACE_ATM_Connector::ACE_ATM_Connector (void)
// Connect the <new_stream> to the <remote_sap>, waiting up to
// <timeout> amount of time if necessary.
-int
+iint
ACE_ATM_Connector::connect (ACE_ATM_Stream &new_stream,
const ACE_ATM_Addr &remote_sap,
ACE_ATM_Params params,
diff --git a/ace/ATM/ATM_Connector.h b/ace/ATM/ATM_Connector.h
index baa84fd47d6..f7fbcb1cff8 100644
--- a/ace/ATM/ATM_Connector.h
+++ b/ace/ATM/ATM_Connector.h
@@ -14,9 +14,9 @@
#define ACE_ATM_CONNECTOR_H
#include "ace/pre.h"
-#include "ace/ATM_Stream.h"
-#include "ace/ATM_Params.h"
-#include "ace/ATM_QoS.h"
+#include "ace/ATM/ATM_Stream.h"
+#include "ace/ATM/ATM_Params.h"
+#include "ace/ATM/ATM_QoS.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
diff --git a/ace/ATM/ATM_Params.h b/ace/ATM/ATM_Params.h
index 5544bd3afcd..2b1e4ec9e0e 100644
--- a/ace/ATM/ATM_Params.h
+++ b/ace/ATM/ATM_Params.h
@@ -23,12 +23,12 @@
#if defined (ACE_HAS_ATM)
#if defined (ACE_HAS_FORE_ATM_XTI)
-#include "ace/TLI.h"
+#include "ace/IPC/TLI.h"
#define ATM_PROTOCOL_DEFAULT 0
typedef struct t_info Param_Info;
typedef struct netbuf Param_Udata;
#elif defined (ACE_HAS_FORE_ATM_WS2)
-#include "ace/SOCK.h"
+#include "ace/Sockets/SOCK.h"
#define ATM_PROTOCOL_DEFAULT ATMPROTO_AAL5
#define ACE_XTI_ATM_DEVICE ""
typedef int Param_Info;
@@ -176,7 +176,7 @@ private:
};
#if defined (__ACE_INLINE__)
-#include "ace/ATM_Params.i"
+#include "ace/ATM/ATM_Params.i"
#endif /* __ACE_INLINE__ */
#endif /* ACE_HAS_ATM */
diff --git a/ace/ATM/ATM_Stream.cpp b/ace/ATM/ATM_Stream.cpp
index 997e36122ba..97785123e09 100644
--- a/ace/ATM/ATM_Stream.cpp
+++ b/ace/ATM/ATM_Stream.cpp
@@ -1,13 +1,13 @@
// $Id$
-#include "ace/ATM_Stream.h"
+#include "ace/ATM/ATM_Stream.h"
ACE_RCSID (ace, ATM_Stream, "$Id$")
#if defined (ACE_HAS_ATM)
#if !defined (__ACE_INLINE__)
-#include "ace/ATM_Stream.i"
+#include "ace/ATM/ATM_Stream.i"
#endif /* __ACE_INLINE__ */
ACE_ALLOC_HOOK_DEFINE (ACE_ATM_Stream)
diff --git a/ace/ATM/ATM_Stream.h b/ace/ATM/ATM_Stream.h
index f9dd3741f96..098764728bf 100644
--- a/ace/ATM/ATM_Stream.h
+++ b/ace/ATM/ATM_Stream.h
@@ -15,8 +15,8 @@
#define ACE_ATM_STREAM_H
#include "ace/pre.h"
-#include "ace/ATM_Addr.h"
-#include "ace/ATM_Params.h"
+#include "ace/ATM/ATM_Addr.h"
+#include "ace/ATM/ATM_Params.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
@@ -25,10 +25,10 @@
#if defined (ACE_HAS_ATM)
#if defined (ACE_WIN32)
-#include "SOCK_Stream.h"
+#include "ace/Sockets/SOCK_Stream.h"
typedef ACE_SOCK_Stream ATM_Stream;
#else
-#include "TLI_Stream.h"
+#include "ace/IPC/TLI_Stream.h"
typedef ACE_TLI_Stream ATM_Stream;
#endif
@@ -88,7 +88,7 @@ private:
};
#if defined (__ACE_INLINE__)
-#include "ace/ATM_Stream.i"
+#include "ace/ATM/ATM_Stream.i"
#endif /* __ACE_INLINE__ */
#endif /* ACE_HAS_ATM */
diff --git a/ace/ATM/Makefile b/ace/ATM/Makefile
index c519719e86a..09481984ace 100644
--- a/ace/ATM/Makefile
+++ b/ace/ATM/Makefile
@@ -10,7 +10,7 @@ LIB = $(LIBOS).a
SHLIB = $(LIBOS).$(SOEXT)
-OS_FILES = \
+LIB_FILES = \
ATM_Acceptor\
ATM_Addr\
ATM_Connector\
@@ -27,7 +27,7 @@ include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
####
#### ACE_COMPONENTS support.
####
-FILES += $(OS_FILES)
+FILES += $(LIB_FILES)
LSRC = $(addsuffix .cpp,$(FILES))
diff --git a/ace/Connection/Acceptor.cpp b/ace/Connection/Acceptor.cpp
new file mode 100644
index 00000000000..2d9cad5e54f
--- /dev/null
+++ b/ace/Connection/Acceptor.cpp
@@ -0,0 +1,1184 @@
+// $Id$
+
+#ifndef ACE_ACCEPTOR_C
+#define ACE_ACCEPTOR_C
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Acceptor.h"
+#include "ace/Handle_Set.h"
+#include "ace/WFMO_Reactor.h"
+
+ACE_RCSID(ace, Acceptor, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Acceptor)
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->peer_acceptor_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
+ return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
+ return ACE_const_cast (ACE_PEER_ACCEPTOR &, this->peer_acceptor_);
+}
+
+// Returns ACE_HANDLE of the underlying Acceptor_Strategy.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
+ return this->peer_acceptor_.get_handle ();
+}
+
+// Initialize the appropriate strategies for creation, passive
+// connection acceptance, and concurrency, and then register <this>
+// with the Reactor and listen for connection requests at the
+// designated <local_addr>.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ int flags,
+ int use_select,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
+ this->flags_ = flags;
+ this->use_select_ = use_select;
+ this->reuse_addr_ = reuse_addr;
+ this->peer_acceptor_addr_ = local_addr;
+
+ // Must supply a valid Reactor to Acceptor::open()...
+
+ if (reactor == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (this->peer_acceptor_.open (local_addr, reuse_addr) == -1)
+ return -1;
+
+ // Set the peer acceptor's handle into non-blocking mode. This is a
+ // safe-guard against the race condition that can otherwise occur
+ // between the time when <select> indicates that a passive-mode
+ // socket handle is "ready" and when we call <accept>. During this
+ // interval, the client can shutdown the connection, in which case,
+ // the <accept> call can hang!
+ this->peer_acceptor_.enable (ACE_NONBLOCK);
+
+ int result = reactor->register_handler (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+ if (result != -1)
+ this->reactor (reactor);
+
+ return result;
+}
+
+// Simple constructor.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor (ACE_Reactor *reactor,
+ int use_select)
+ :flags_ (0),
+ use_select_ (use_select),
+ reuse_addr_ (1)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor");
+
+ this->reactor (reactor);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor
+ (const ACE_PEER_ACCEPTOR_ADDR &addr,
+ ACE_Reactor *reactor,
+ int flags,
+ int use_select,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor");
+
+ if (this->open (addr,
+ reactor,
+ flags,
+ use_select,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Acceptor::ACE_Acceptor")));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Acceptor (void)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Acceptor");
+ this->handle_close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
+ return ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close ();
+}
+
+// Hook called by the explicit dynamic linking facility.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init");
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info");
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_TCHAR addr_str[BUFSIZ];
+ ACE_PEER_ACCEPTOR_ADDR addr;
+
+ if (this->acceptor ().get_local_addr (addr) == -1)
+ return -1;
+ else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s\t %s %s"),
+ ACE_LIB_TEXT ("ACE_Acceptor"),
+ addr_str,
+ ACE_LIB_TEXT ("# acceptor factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");
+ return this->reactor ()->suspend_handler (this);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");
+ return this->reactor ()->resume_handler (this);
+}
+
+// Perform termination activities when <this> is removed from the
+// <reactor>.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close (void)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close");
+ return this->handle_close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");
+ // Guard against multiple closes.
+ if (this->reactor () != 0)
+ {
+ ACE_HANDLE handle = this->get_handle ();
+
+ this->reactor ()->remove_handler
+ (handle,
+ // We must pass the DONT_CALL flag here to avoid infinite
+ // recursion.
+ ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
+
+ // Shut down the listen socket to recycle the handles.
+ if (this->peer_acceptor_.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("close\n")));
+ // Set the Reactor to 0 so that we don't try to close down
+ // again.
+ this->reactor (0);
+ }
+ return 0;
+}
+
+// Bridge method for creating a SVC_HANDLER. The strategy for
+// creating a SVC_HANDLER are configured into the Acceptor via it's
+// <creation_strategy_>. The default is to create a new SVC_HANDLER.
+// However, subclasses can override this strategy to perform
+// SVC_HANDLER creation in any way that they like (such as creating
+// subclass instances of SVC_HANDLER, using a singleton, dynamically
+// linking the handler, etc.).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler");
+
+ if (sh == 0)
+ ACE_NEW_RETURN (sh,
+ SVC_HANDLER,
+ -1);
+
+ // Set the reactor of the newly created <SVC_HANDLER> to the same
+ // reactor that this <ACE_Acceptor> is using.
+ if (this->reactor ())
+ sh->reactor (this->reactor ());
+
+ return 0;
+}
+
+// Bridge method for accepting the new connection into the
+// <svc_handler>. The default behavior delegates to the
+// <PEER_ACCEPTOR::accept> in the Acceptor_Strategy.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler");
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle = this->reactor ()->uses_event_associations ();
+
+ if (this->acceptor ().accept (svc_handler->peer (), // stream
+ 0, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle // reset new handler
+ ) == -1)
+ {
+ // Close down handler to avoid memory leaks.
+ svc_handler->close (0);
+
+ return -1;
+ }
+ else
+ return 0;
+}
+
+// Bridge method for activating a <svc_handler> with the appropriate
+// concurrency strategy. The default behavior of this method is to
+// activate the SVC_HANDLER by calling its open() method (which allows
+// the SVC_HANDLER to define its own concurrency strategy). However,
+// subclasses can override this strategy to do more sophisticated
+// concurrency activations (such as creating the SVC_HANDLER as an
+// "active object" via multi-threading or multi-processing).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");
+
+ int result = 0;
+
+ // See if we should enable non-blocking I/O on the <svc_handler>'s
+ // peer.
+ if (ACE_BIT_ENABLED (this->flags_,
+ ACE_NONBLOCK))
+ {
+ if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
+ result = -1;
+ }
+ // Otherwise, make sure it's disabled by default.
+ else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
+ result = -1;
+
+ if (result == 0 && svc_handler->open ((void *) this) == -1)
+ result = -1;
+
+ if (result == -1)
+ svc_handler->close (0);
+
+ return result;
+}
+
+// Template Method that makes a SVC_HANDLER (using the appropriate
+// creation strategy), accept the connection into the SVC_HANDLER, and
+// then activate the SVC_HANDLER.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input (ACE_HANDLE listener)
+{
+ ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input");
+ ACE_Handle_Set conn_handle;
+
+ // Default is "timeout (0, 0)," which means "poll."
+ ACE_Time_Value timeout;
+
+ // Accept connections from clients. Note that a loop is used for two
+ // reasons:
+ //
+ // 1. It allows us to accept all pending connections without an
+ // extra trip through the ACE_Reactor and without having to use
+ // non-blocking I/O...
+ //
+ // 2. It allows the TLI_SAP::ACE_Acceptor class to work correctly (don't
+ // ask -- TLI is *horrible*...).
+
+ // @@ What should we do if any of the substrategies fail? Right
+ // now, we just print out a diagnostic message if <ACE::debug>
+ // returns > 0 and return 0 (which means that the Acceptor remains
+ // registered with the Reactor)...
+ do
+ {
+ // Create a service handler, using the appropriate creation
+ // strategy.
+
+ SVC_HANDLER *svc_handler = 0;
+
+ if (this->make_svc_handler (svc_handler) == -1)
+ {
+ if (ACE::debug () > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("make_svc_handler")));
+ return 0;
+ }
+ // Accept connection into the Svc_Handler.
+
+ else if (this->accept_svc_handler (svc_handler) == -1)
+ {
+ if (ACE::debug () > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("accept_svc_handler")));
+ return 0;
+ }
+
+ // Activate the <svc_handler> using the designated concurrency
+ // strategy (note that this method becomes responsible for
+ // handling errors and freeing up the memory if things go
+ // awry...).
+ else if (this->activate_svc_handler (svc_handler) == -1)
+ {
+ if (ACE::debug () > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("activate_svc_handler")));
+ return 0;
+ }
+
+ conn_handle.set_bit (listener);
+ }
+
+ // Now, check to see if there is another connection pending and
+ // break out of the loop if there is none.
+ while (this->use_select_
+ && ACE_OS::select (int (listener) + 1,
+ conn_handle,
+ 0,
+ 0,
+ &timeout) == 1);
+ return 0;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Strategy_Acceptor)
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");
+
+ // First suspend the SVC_HANDLER's we've created.
+ if (this->scheduling_strategy_->suspend () == -1)
+ return -1;
+ else // Then suspend ourselves.
+ return ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");
+
+ // First resume ourselves.
+ if (ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume () == -1)
+ return -1;
+ else // Then resume the SVC_HANDLER's we've created.
+ return this->scheduling_strategy_->resume ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump ();
+ this->creation_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_creation_strategy_ = %d"), delete_creation_strategy_));
+ this->accept_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_accept_strategy_ = %d"), delete_accept_strategy_));
+ this->concurrency_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_));
+ this->scheduling_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_scheduling_strategy_ = %d"), delete_scheduling_strategy_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_name_ = %s"),
+ this->service_name_ == 0 ? ACE_LIB_TEXT ("<unknown>") : this->service_name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_description_ = %s"),
+ this->service_description_ == 0 ? ACE_LIB_TEXT ("<unknown>") : this->service_description_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_port_ = %d"), this->service_port_));
+ this->service_addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
+ return this->accept_strategy_->acceptor ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
+ return this->accept_strategy_->acceptor ();
+}
+
+// Returns ACE_HANDLE of the underlying Acceptor_Strategy.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
+ return this->accept_strategy_->get_handle ();
+}
+
+// Initialize the appropriate strategies for creation, passive
+// connection acceptance, and concurrency, and then register <this>
+// with the Reactor and listen for connection requests at the
+// designated <local_addr>.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
+ const ACE_TCHAR *service_name,
+ const ACE_TCHAR *service_description,
+ int use_select)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
+
+ if (this->service_name_ == 0 && service_name != 0)
+ ACE_ALLOCATOR_RETURN (this->service_name_,
+ ACE_OS::strdup (service_name),
+ -1);
+ if (this->service_description_ == 0 && service_description != 0)
+ ACE_ALLOCATOR_RETURN (this->service_description_,
+ ACE_OS::strdup (service_description),
+ -1);
+ this->reactor (reactor);
+
+ // Must supply a valid Reactor to Acceptor::open()...
+ if (reactor == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Initialize the creation strategy.
+
+ if (cre_s == 0)
+ {
+ ACE_NEW_RETURN (cre_s,
+ CREATION_STRATEGY,
+ -1);
+ this->delete_creation_strategy_ = 1;
+ }
+ this->creation_strategy_ = cre_s;
+
+ // Initialize the accept strategy.
+
+ if (acc_s == 0)
+ {
+ ACE_NEW_RETURN (acc_s,
+ ACCEPT_STRATEGY (this->reactor ()),
+ -1);
+ this->delete_accept_strategy_ = 1;
+ }
+ this->accept_strategy_ = acc_s;
+
+ if (this->accept_strategy_->open (local_addr, 1) == -1)
+ return -1;
+
+ // Set the peer acceptor's handle into non-blocking mode. This is a
+ // safe-guard against the race condition that can otherwise occur
+ // between the time when <select> indicates that a passive-mode
+ // socket handle is "ready" and when we call <accept>. During this
+ // interval, the client can shutdown the connection, in which case,
+ // the <accept> call can hang!
+ if (this->accept_strategy_->acceptor ().enable (ACE_NONBLOCK) != 0)
+ return -1;
+
+ // Initialize the concurrency strategy.
+
+ if (con_s == 0)
+ {
+ ACE_NEW_RETURN (con_s,
+ CONCURRENCY_STRATEGY,
+ -1);
+ this->delete_concurrency_strategy_ = 1;
+ }
+ this->concurrency_strategy_ = con_s;
+
+ // Initialize the scheduling strategy.
+
+ if (sch_s == 0)
+ {
+ ACE_NEW_RETURN (sch_s,
+ SCHEDULING_STRATEGY,
+ -1);
+ this->delete_scheduling_strategy_ = 1;
+ }
+ this->scheduling_strategy_ = sch_s;
+
+ this->use_select_ = use_select;
+
+ return this->reactor ()->register_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+}
+
+// Simple constructor.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor
+ (const ACE_TCHAR service_name[],
+ const ACE_TCHAR service_description[],
+ int use_select)
+ : creation_strategy_ (0),
+ delete_creation_strategy_ (0),
+ accept_strategy_ (0),
+ delete_accept_strategy_ (0),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (0),
+ scheduling_strategy_ (0),
+ delete_scheduling_strategy_ (0),
+ service_name_ (0),
+ service_description_ (0),
+ service_port_ (0)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor");
+
+ if (service_name != 0)
+ ACE_ALLOCATOR (this->service_name_,
+ ACE_OS::strdup (service_name));
+ if (service_description != 0)
+ ACE_ALLOCATOR (this->service_description_,
+ ACE_OS::strdup (service_description));
+ this->use_select_ = use_select;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor
+ (const ACE_PEER_ACCEPTOR_ADDR &addr,
+ ACE_Reactor *reactor,
+ ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
+ const ACE_TCHAR service_name[],
+ const ACE_TCHAR service_description[],
+ int use_select)
+ : creation_strategy_ (0),
+ delete_creation_strategy_ (0),
+ accept_strategy_ (0),
+ delete_accept_strategy_ (0),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (0),
+ scheduling_strategy_ (0),
+ delete_scheduling_strategy_ (0),
+ service_name_ (0),
+ service_description_ (0),
+ service_port_ (0)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor");
+
+ if (this->open (addr,
+ reactor,
+ cre_s,
+ acc_s,
+ con_s,
+ sch_s,
+ service_name,
+ service_description,
+ use_select) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Strategy_Acceptor::ACE_Strategy_Acceptor")));
+}
+
+// Perform termination activities when <this> is removed from the
+// <ACE_Reactor>.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");
+ // Guard against multiple closes.
+ if (this->reactor () != 0)
+ {
+ ACE_HANDLE handle = this->get_handle ();
+
+ if (this->delete_creation_strategy_)
+ delete this->creation_strategy_;
+ this->delete_creation_strategy_ = 0;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_accept_strategy_)
+ delete this->accept_strategy_;
+ this->delete_accept_strategy_ = 0;
+ this->accept_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = 0;
+ this->concurrency_strategy_ = 0;
+
+ if (this->delete_scheduling_strategy_)
+ delete this->scheduling_strategy_;
+ this->delete_scheduling_strategy_ = 0;
+ this->scheduling_strategy_ = 0;
+
+ // We must use the <handle> obtained *before* we deleted the
+ // accept_strategy_...
+
+ this->reactor ()->remove_handler
+ (handle,
+ ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
+
+ // Set the Reactor to 0 so that we don't try to close down
+ // again.
+ this->reactor (0);
+ }
+ return 0;
+}
+
+// Bridge method for creating a <SVC_HANDLER>. The strategy for
+// creating a <SVC_HANDLER> are configured into the Acceptor via it's
+// <creation_strategy_>. The default is to create a new
+// <SVC_HANDLER>. However, subclasses can override this strategy to
+// perform <SVC_HANDLER> creation in any way that they like (such as
+// creating subclass instances of <SVC_HANDLER>, using a singleton,
+// dynamically linking the handler, etc.).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler");
+ return this->creation_strategy_->make_svc_handler (sh);
+}
+
+// Bridge method for accepting the new connection into the
+// <svc_handler>. The default behavior delegates to the
+// <Strategy_Acceptor::accept> in the Acceptor_Strategy.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler");
+ return this->accept_strategy_->accept_svc_handler (svc_handler);
+}
+
+// Bridge method for activating a <svc_handler> with the appropriate
+// concurrency strategy. The default behavior of this method is to
+// activate the SVC_HANDLER by calling its open() method (which allows
+// the SVC_HANDLER to define its own concurrency strategy). However,
+// subclasses can override this strategy to do more sophisticated
+// concurrency activations (such as creating the SVC_HANDLER as an
+// "active object" via multi-threading or multi-processing).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");
+ return this->concurrency_strategy_->activate_svc_handler
+ (svc_handler,
+ (void *) this);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Strategy_Acceptor (void)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Strategy_Acceptor");
+ ACE_OS::free ((void *) this->service_name_);
+ ACE_OS::free ((void *) this->service_description_);
+ this->handle_close ();
+}
+
+// Signal the server to shutdown gracefully.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_Reactor::end_event_loop ();
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor::info");
+
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_TCHAR service_addr_str[BUFSIZ];
+ ACE_PEER_ACCEPTOR_ADDR addr;
+
+ if (this->acceptor ().get_local_addr (addr) == -1)
+ return -1;
+ else if (addr.addr_to_string (service_addr_str,
+ sizeof service_addr_str) == -1)
+ return -1;
+
+ // @@ Should add the protocol in...
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s\t %s #%s\n"),
+ this->service_name_ == 0
+ ? ACE_LIB_TEXT ("<unknown>")
+ : this->service_name_,
+ service_addr_str,
+ this->service_description_ == 0
+ ? ACE_LIB_TEXT ("<unknown>")
+ : this->service_description_);
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
+{
+ ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
+ return this->ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close ();
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Oneshot_Acceptor)
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsvc_handler_ = %x"), this->svc_handler_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nrestart_ = %d"), this->restart_));
+ this->peer_acceptor_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_concurrency_strategy_ = %d"),
+ delete_concurrency_strategy_));
+ this->concurrency_strategy_->dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
+ this->reactor (reactor);
+
+ // Initialize the concurrency strategy.
+
+ if (con_s == 0)
+ {
+ ACE_NEW_RETURN (con_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER>,
+ -1);
+ this->delete_concurrency_strategy_ = 1;
+ }
+ this->concurrency_strategy_ = con_s;
+
+ // Reuse the addr, even if it is already in use...!
+ return this->peer_acceptor_.open (local_addr, 1);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor (void)
+ : delete_concurrency_strategy_ (0)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor");
+ this->reactor (0);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *cs)
+ : delete_concurrency_strategy_ (0)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor");
+ if (this->open (local_addr, reactor, cs) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor")));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Oneshot_Acceptor (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Oneshot_Acceptor");
+ this->handle_close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close");
+ return this->handle_close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");
+
+ // Guard against multiple closes.
+ if (this->delete_concurrency_strategy_)
+ {
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = 0;
+ this->concurrency_strategy_ = 0;
+
+ // Note that if we aren't actually registered with the
+ // ACE_Reactor then it's ok for this call to fail...
+
+ if (this->reactor ())
+ this->reactor ()->remove_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
+
+ if (this->peer_acceptor_.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("close\n")));
+ }
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_timeout
+ (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_timeout");
+ errno = ETIME;
+
+ if (this->svc_handler_->handle_timeout (tv, arg) == -1)
+ this->svc_handler_->handle_close (this->svc_handler_->get_handle (),
+ ACE_Event_Handler::TIMER_MASK);
+
+ // Since we aren't necessarily registered with the Reactor, don't
+ // bother to check the return value here...
+ if (this->reactor ())
+ this->reactor ()->remove_handler (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::cancel (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::cancel");
+ return this->reactor () && this->reactor ()->cancel_timer (this);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::register_handler
+ (SVC_HANDLER *svc_handler,
+ const ACE_Synch_Options &synch_options,
+ int restart)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::register_handler");
+ // Can't do this if we don't have a Reactor.
+ if (this->reactor () == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ this->svc_handler_ = svc_handler;
+ this->restart_ = restart;
+ ACE_Time_Value *tv = (ACE_Time_Value *) synch_options.time_value ();
+
+ if (tv != 0
+ && this->reactor ()->schedule_timer (this,
+ synch_options.arg (),
+ *tv) == 0)
+ return -1;
+ else
+ return this->reactor ()->register_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+ }
+}
+
+// Bridge method for activating a <svc_handler> with the appropriate
+// concurrency strategy. The default behavior of this method is to
+// activate the SVC_HANDLER by calling its open() method (which allows
+// the SVC_HANDLER to define its own concurrency strategy). However,
+// subclasses can override this strategy to do more sophisticated
+// concurrency activations (such as creating the SVC_HANDLER as an
+// "active object" via multi-threading or multi-processing).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");
+ return this->concurrency_strategy_->activate_svc_handler
+ (svc_handler,
+ (void *) this);
+}
+
+// Factors out the code shared between the <accept> and <handle_input>
+// methods.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::shared_accept
+ (SVC_HANDLER *svc_handler,
+ ACE_PEER_ACCEPTOR_ADDR *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::shared_accept");
+ if (svc_handler == 0)
+ return -1;
+
+ // Accept connection into the Svc_Handler.
+ else if (this->peer_acceptor_.accept (svc_handler->peer (), // stream
+ remote_addr, // remote address
+ timeout, // timeout
+ restart, // restart
+ reset_new_handle // reset new handle
+ ) == -1)
+ {
+ // Check whether we just timed out or whether we failed...
+ if (!(errno == EWOULDBLOCK || errno == ETIME))
+ // Close down handler to avoid memory leaks.
+ svc_handler->close (0);
+ return -1;
+ }
+ // Activate the <svc_handler> using the designated concurrency
+ // strategy (note that this method becomes responsible for handling
+ // errors and freeing up the memory if things go awry...)
+ else
+ return this->activate_svc_handler (svc_handler);
+}
+
+// Make a SVC_HANDLER, accept the connection into the SVC_HANDLER, and
+// then activate the SVC_HANDLER. Note that SVC_HANDLER::open()
+// decides what type of concurrency strategy to use.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept
+ (SVC_HANDLER *svc_handler,
+ ACE_PEER_ACCEPTOR_ADDR *remote_addr,
+ const ACE_Synch_Options &synch_options,
+ int restart,
+ int reset_new_handle)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept");
+ // Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y >
+ // 0) then this->connector_.connect() will block synchronously. If
+ // <use_reactor> is set then we don't want this to happen (since we
+ // want the ACE_Reactor to do the timeout asynchronously).
+ // Therefore, we'll force this->connector_ to use ACE_Time_Value (0,
+ // 0) in this case...
+
+ ACE_Time_Value *timeout;
+ int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
+
+ if (use_reactor)
+ timeout = (ACE_Time_Value *) &ACE_Time_Value::zero;
+ else
+ timeout = (ACE_Time_Value *) synch_options.time_value ();
+
+ if (this->shared_accept (svc_handler, // stream
+ remote_addr, // remote address
+ timeout, // timeout
+ restart, // restart
+ reset_new_handle // reset new handler
+ ) == -1)
+ {
+ if (use_reactor && errno == EWOULDBLOCK)
+ // We couldn't accept right away, so let's wait in the
+ // <ACE_Reactor>.
+ this->register_handler (svc_handler,
+ synch_options,
+ restart);
+ return -1;
+ }
+ return 0;
+}
+
+// Accepts one pending connection from a client (since we're the
+// "oneshot" Acceptor).
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input");
+ int result = 0;
+
+ // Cancel any timer that might be pending.
+ this->cancel ();
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle = this->reactor ()->uses_event_associations ();
+
+ // There is a use-case whereby this object will be gone upon return
+ // from shared_accept - if the Svc_Handler deletes this Oneshot_Acceptor
+ // during the shared_accept/activation steps. So, do whatever we need
+ // to do with this object before calling shared_accept.
+ if (this->reactor ())
+ this->reactor ()->remove_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
+
+ if (this->shared_accept (this->svc_handler_, // stream
+ 0, // remote address
+ 0, // timeout
+ this->restart_, // restart
+ reset_new_handle // reset new handle
+ ) == -1)
+ result = -1;
+
+ return result;
+}
+
+// Hook called by the explicit dynamic linking facility.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init");
+ return -1;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
+ return this->handle_close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info");
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_TCHAR addr_str[BUFSIZ];
+ ACE_PEER_ACCEPTOR_ADDR addr;
+
+ if (this->peer_acceptor_.get_local_addr (addr) == -1)
+ return -1;
+ else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s\t %s %s"),
+ ACE_LIB_TEXT ("ACE_Oneshot_Acceptor"),
+ addr_str,
+ ACE_LIB_TEXT ("#oneshot acceptor factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");
+ return this->reactor () && this->reactor ()->suspend_handler (this);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");
+ return this->reactor () && this->reactor ()->resume_handler (this);
+}
+
+// Returns ACE_HANDLE of the underlying peer_acceptor.
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
+ return this->peer_acceptor_.get_handle ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
+ return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
+{
+ ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
+ return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
+}
+
+#endif /* ACE_ACCEPTOR_C */
diff --git a/ace/Connection/Acceptor.h b/ace/Connection/Acceptor.h
new file mode 100644
index 00000000000..63a448f1046
--- /dev/null
+++ b/ace/Connection/Acceptor.h
@@ -0,0 +1,567 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ACCEPTOR_H
+#define ACE_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Object.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Strategies_T.h"
+
+/**
+ * @class ACE_Acceptor
+ *
+ * @brief Abstract factory for creating a service handler
+ * (SVC_HANDLER), accepting into the SVC_HANDLER, and
+ * activating the SVC_HANDLER.
+ *
+ * Implements the basic strategy for passively establishing
+ * connections with clients. An ACE_Acceptor is parameterized
+ * by concrete types that conform to the interfaces of
+ * PEER_ACCEPTOR and SVC_HANDLER. The PEER_ACCEPTOR is
+ * instantiated with a transport mechanism that passively
+ * establishes connections. The SVC_HANDLER is instantiated
+ * with a concrete type that performs the application-specific
+ * service. An ACE_Acceptor inherits from ACE_Service_Object,
+ * which in turn inherits from ACE_Event_Handler. This enables
+ * the ACE_Reactor to dispatch the ACE_Acceptor's handle_input
+ * method when connection events occur. The handle_input method
+ * performs the ACE_Acceptor's default creation, connection
+ * establishment, and service activation strategies. These
+ * strategies can be overridden by subclasses individually or as
+ * a group.
+ */
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class ACE_Acceptor : public ACE_Service_Object
+{
+public:
+ // = Initialization and termination methods.
+ /// "Do-nothing" constructor.
+ ACE_Acceptor (ACE_Reactor * = 0,
+ int use_select = 1);
+
+ /**
+ * Initialize and register <this> with the Reactor and listen for
+ * connection requests at the designated <local_addr>. <flags>
+ * indicates how <SVC_HANDLER>'s should be initialized prior to
+ * being activated. Right now, the only flag that is processed is
+ * <ACE_NONBLOCK>, which enabled non-blocking I/O on the
+ * <SVC_HANDLER> when it is opened. If <use_select> is non-zero
+ * then <select> is used to determine when to break out of the
+ * <accept> loop. <reuse_addr> is passed down to the
+ * <PEER_ACCEPTOR>. If it is non-zero this will allow the OS to
+ * reuse this listen port.
+ */
+ ACE_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor * = ACE_Reactor::instance (),
+ int flags = 0,
+ int use_select = 1,
+ int reuse_addr = 1);
+
+ /**
+ * Initialize and register <this> with the Reactor and listen for
+ * connection requests at the designated <local_addr>. <flags>
+ * indicates how <SVC_HANDLER>'s should be initialized prior to
+ * being activated. Right now, the only flag that is processed is
+ * <ACE_NONBLOCK>, which enabled non-blocking I/O on the
+ * <SVC_HANDLER> when it is opened. If <use_select> is non-zero
+ * then <select> is used to determine when to break out of the
+ * <accept> loop. <reuse_addr> is passed down to the
+ * <PEER_ACCEPTOR>. If it is non-zero this will allow the OS to
+ * reuse this listen port.
+ */
+ int open (const ACE_PEER_ACCEPTOR_ADDR &,
+ ACE_Reactor * = ACE_Reactor::instance (),
+ int flags = 0,
+ int use_select = 1,
+ int reuse_addr = 1);
+
+ /// Close down the Acceptor's resources.
+ virtual ~ACE_Acceptor (void);
+
+ /// Return the underlying PEER_ACCEPTOR object.
+ virtual operator ACE_PEER_ACCEPTOR &() const;
+
+ /// Return the underlying PEER_ACCEPTOR object.
+ virtual ACE_PEER_ACCEPTOR &acceptor (void) const;
+
+ /// Returns the listening acceptor's <ACE_HANDLE>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Close down the Acceptor
+ virtual int close (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = The following three methods define the Acceptor's strategies
+ // for creating, accepting, and activating SVC_HANDLER's,
+ // respectively.
+
+ /**
+ * Bridge method for creating a SVC_HANDLER. The default is to
+ * create a new <SVC_HANDLER> if <sh> == 0, else <sh> is unchanged.
+ * However, subclasses can override this policy to perform
+ * SVC_HANDLER creation in any way that they like (such as creating
+ * subclass instances of SVC_HANDLER, using a singleton, dynamically
+ * linking the handler, etc.). Returns -1 on failure, else 0.
+ */
+ virtual int make_svc_handler (SVC_HANDLER *&sh);
+
+ /**
+ * Bridge method for accepting the new connection into the
+ * <svc_handler>. The default behavior delegates to the
+ * PEER_ACCEPTOR::accept.
+ */
+ virtual int accept_svc_handler (SVC_HANDLER *svc_handler);
+
+ /**
+ * Bridge method for activating a <svc_handler> with the appropriate
+ * concurrency strategy. The default behavior of this method is to
+ * activate the SVC_HANDLER by calling its <open> method (which
+ * allows the SVC_HANDLER to define its own concurrency strategy).
+ * However, subclasses can override this strategy to do more
+ * sophisticated concurrency activations (such as making the
+ * SVC_HANDLER as an "active object" via multi-threading or
+ * multi-processing).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ // = Demultiplexing hooks.
+ /// Perform termination activities when <this> is removed from the
+ /// <reactor>.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Accepts all pending connections from clients, and creates and
+ /// activates SVC_HANDLERs.
+ virtual int handle_input (ACE_HANDLE);
+
+ // = Dynamic linking hooks.
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Calls <handle_close>.
+ virtual int fini (void);
+
+ /// Default version returns address info in <buf>.
+ virtual int info (ACE_TCHAR **buf, size_t) const;
+
+public:
+ // = Service management hooks.
+ /// This method calls <Reactor::suspend>.
+ virtual int suspend (void);
+
+ /// This method calls <Reactor::resume>.
+ virtual int resume (void);
+
+protected:
+ /// Concrete factory for accepting connections from clients...
+ ACE_PEER_ACCEPTOR peer_acceptor_;
+
+ /// Needed to reopen the socket if <accept> fails.
+ ACE_PEER_ACCEPTOR_ADDR peer_acceptor_addr_;
+
+ /**
+ * Flags that indicate how <SVC_HANDLER>'s should be initialized
+ * prior to being activated. Right now, the only flag that is
+ * processed is <ACE_NONBLOCK>, which enabled non-blocking I/O on
+ * the <SVC_HANDLER> when it is opened.
+ */
+ int flags_;
+
+ /// Flag that indicates whether it shall use <select> in the
+ /// <accept>-loop.
+ int use_select_;
+
+ /// Needed to reopen the socket if <accept> fails.
+ int reuse_addr_;
+};
+
+/**
+ * @class ACE_Strategy_Acceptor
+ *
+ * @brief Abstract factory for creating a service handler
+ * (SVC_HANDLER), accepting into the SVC_HANDLER, and activating
+ * the SVC_HANDLER.
+ *
+ * Implements a flexible and extensible set of strategies for
+ * passively establishing connections with clients. There are
+ * three main strategies: (1) creating a SVC_HANDLER, (2)
+ * passively accepting a new connection from a client into the
+ * SVC_HANDLER, and (3) activating the SVC_HANDLER with a
+ * particular concurrency mechanism.
+ */
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class ACE_Strategy_Acceptor : public ACE_Acceptor <SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Strategy_Acceptor (const ACE_TCHAR service_name[] = 0,
+ const ACE_TCHAR service_description[] = 0,
+ int use_select = 1);
+
+ /**
+ * Initialize the appropriate strategies for creation, passive
+ * connection acceptance, and concurrency, and then register <this>
+ * with the Reactor and listen for connection requests at the
+ * designated <local_addr>.
+ */
+ ACE_Strategy_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor * = ACE_Reactor::instance (),
+ ACE_Creation_Strategy<SVC_HANDLER> * = 0,
+ ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> * = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
+ ACE_Scheduling_Strategy<SVC_HANDLER> * = 0,
+ const ACE_TCHAR service_name[] = 0,
+ const ACE_TCHAR service_description[] = 0,
+ int use_select = 1);
+
+ /**
+ * Initialize the appropriate strategies for creation, passive
+ * connection acceptance, and concurrency, and then register <this>
+ * with the Reactor and listen for connection requests at the
+ * designated <local_addr>.
+ */
+ int open (const ACE_PEER_ACCEPTOR_ADDR &,
+ ACE_Reactor * = ACE_Reactor::instance (),
+ ACE_Creation_Strategy<SVC_HANDLER> * = 0,
+ ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> * = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
+ ACE_Scheduling_Strategy<SVC_HANDLER> * = 0,
+ const ACE_TCHAR *service_name = 0,
+ const ACE_TCHAR *service_description = 0,
+ int use_select = 1);
+
+ /// Close down the Strategy_Acceptor's resources.
+ virtual ~ACE_Strategy_Acceptor (void);
+
+ /// Return the underlying PEER_ACCEPTOR object.
+ virtual operator ACE_PEER_ACCEPTOR &() const;
+
+ /// Return the underlying PEER_ACCEPTOR object.
+ virtual ACE_PEER_ACCEPTOR &acceptor (void) const;
+
+ /// Returns the listening acceptor's <ACE_HANDLE>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Service management hooks.
+
+ /// This method delegates to the <Scheduling_Strategy>'s <suspend>
+ /// method.
+ virtual int suspend (void);
+
+ /// This method delegates to the <Scheduling_Strategy>'s <resume>
+ /// method.
+ virtual int resume (void);
+
+ /// Calls <handle_close> when dynamically unlinked.
+ virtual int fini (void);
+
+ /// Default version returns address info in <buf>.
+ virtual int info (ACE_TCHAR **buf, size_t) const;
+
+ // = The following three methods define the <Acceptor>'s strategies
+ // for creating, accepting, and activating <SVC_HANDLER>'s,
+ // respectively.
+
+ /**
+ * Bridge method for creating a <SVC_HANDLER>. The strategy for
+ * creating a <SVC_HANDLER> are configured into the Acceptor via
+ * it's <creation_strategy_>. The default is to create a new
+ * <SVC_HANDLER> if <sh> == 0, else <sh> is unchanged. However,
+ * subclasses can override this policy to perform <SVC_HANDLER>
+ * creation in any way that they like (such as creating subclass
+ * instances of <SVC_HANDLER>, using a singleton, dynamically
+ * linking the handler, etc.). Returns -1 on failure, else 0.
+ */
+ virtual int make_svc_handler (SVC_HANDLER *&);
+
+ /**
+ * Bridge method for accepting the new connection into the
+ * <SVC_HANDLER>. The default behavior delegates to the
+ * <PEER_ACCEPTOR::accept> in the <Acceptor_Strategy>.
+ */
+ virtual int accept_svc_handler (SVC_HANDLER *svc_handler);
+
+ /**
+ * Bridge method for activating a <SVC_HANDLER> with the appropriate
+ * concurrency strategy. The default behavior of this method is to
+ * activate the <SVC_HANDLER> by calling its <open> method (which
+ * allows the <SVC_HANDLER> to define its own concurrency strategy).
+ * However, subclasses can override this strategy to do more
+ * sophisticated concurrency activations (such as creating the
+ * <SVC_HANDLER> as an "active object" via multi-threading or
+ * multi-processing).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ // = Demultiplexing hooks.
+ /// Perform termination activities when <this> is removed from the
+ /// <Reactor>.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Handle SIGINT.
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+
+ // = These data members are "logically private" but are put in the
+ // protected part in case subclasses want to access them.
+
+ // = Define some useful typedefs.
+ typedef ACE_Creation_Strategy<SVC_HANDLER> CREATION_STRATEGY;
+ typedef ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> ACCEPT_STRATEGY;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> CONCURRENCY_STRATEGY;
+ typedef ACE_Scheduling_Strategy<SVC_HANDLER> SCHEDULING_STRATEGY;
+
+ // = Strategy objects.
+
+ /// Creation strategy for an Acceptor.
+ CREATION_STRATEGY *creation_strategy_;
+
+ /// 1 if <Acceptor> created the creation strategy and thus should
+ /// delete it, else 0.
+ int delete_creation_strategy_;
+
+ /// Accept strategy for an <Acceptor>.
+ ACCEPT_STRATEGY *accept_strategy_;
+
+ /// 1 if <Acceptor> created the accept strategy and thus should delete
+ /// it, else 0.
+ int delete_accept_strategy_;
+
+ /// Concurrency strategy for an <Acceptor>.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// 1 if <Acceptor> created the concurrency strategy and thus should
+ /// delete it, else 0.
+ int delete_concurrency_strategy_;
+
+ /// Scheduling strategy for an <Acceptor>.
+ SCHEDULING_STRATEGY *scheduling_strategy_;
+
+ /// 1 if <Acceptor> created the scheduling strategy and thus should
+ /// delete it, else 0.
+ int delete_scheduling_strategy_;
+
+ // = Service information objects.
+
+ /// Name of the service.
+ ACE_TCHAR *service_name_;
+
+ /// Description of the service.
+ ACE_TCHAR *service_description_;
+
+ /// Port number for the server.
+ u_short service_port_;
+
+ /// Address that the <Strategy_Acceptor> uses to listen for
+ /// connections.
+ ACE_PEER_ACCEPTOR_ADDR service_addr_;
+};
+
+/**
+ * @class ACE_Oneshot_Acceptor
+ *
+ * @brief Generic factory for passively connecting clients and creating
+ * exactly one service handler (SVC_HANDLER).
+ *
+ * This class works similarly to the regular <ACE_Acceptor>,
+ * with the following differences:
+ * 1. This class doesn't automagically register <this> with the
+ * <ACE_Reactor> since it expects to have its <accept> method
+ * called directly. However, it stashes the <ACE_Reactor>
+ * pointer away in case it's needed later to finish accepting
+ * a connection asynchronously.
+ * 2. The class doesn't need an <ACE_Creation_Strategy> (since
+ * the user supplies the SVC_HANDLER) or an
+ * <ACE_Accept_Strategy> (since this class only accepts one
+ * connection and then removes all traces of itself from the
+ * <ACE_Reactor> if it was registered for asynchronous
+ * accepts).
+ */
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class ACE_Oneshot_Acceptor : public ACE_Service_Object
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_Oneshot_Acceptor (void);
+
+ /**
+ * Initialize the appropriate strategies for concurrency and then
+ * open the <peer_acceptor> at the designated <local_addr>. Note
+ * that unlike the <ACE_Acceptor> and <ACE_Strategy_Acceptor>, this
+ * method does NOT register <this> acceptor with the <reactor> at
+ * this point -- it just stashes the <reactor> away in case it's
+ * needed later.
+ */
+ ACE_Oneshot_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ ACE_Reactor *reactor = ACE_Reactor::instance (),
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0);
+
+ /**
+ * Initialize the appropriate strategies for concurrency and then
+ * open the <peer_acceptor> at the designated <local_addr>. Note
+ * that unlike the <ACE_Acceptor> and <ACE_Strategy_Acceptor>, this
+ * method does NOT register <this> acceptor with the <reactor> at
+ * this point -- it just stashes the <reactor> away in case it's
+ * needed later.
+ */
+ int open (const ACE_PEER_ACCEPTOR_ADDR &,
+ ACE_Reactor *reactor = ACE_Reactor::instance (),
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0);
+
+ /// Close down the <Oneshot_Acceptor>.
+ virtual ~ACE_Oneshot_Acceptor (void);
+
+ // = Explicit factory operation.
+ /// Create a <SVC_HANDLER>, accept the connection into the
+ /// <SVC_HANDLER>, and activate the <SVC_HANDLER>.
+ virtual int accept (SVC_HANDLER * = 0,
+ ACE_PEER_ACCEPTOR_ADDR *remote_addr = 0,
+ const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults,
+ int restart = 1,
+ int reset_new_handle = 0);
+
+ /// Cancel a oneshot acceptor that was started asynchronously.
+ virtual int cancel (void);
+
+ /// Return the underlying <PEER_ACCEPTOR> object.
+ virtual operator ACE_PEER_ACCEPTOR &() const;
+
+ /// Return the underlying <PEER_ACCEPTOR> object.
+ virtual ACE_PEER_ACCEPTOR &acceptor (void) const;
+
+ /// Close down the <Oneshot_Acceptor>.
+ virtual int close (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /**
+ * Bridge method for activating a <svc_handler> with the appropriate
+ * concurrency strategy. Default behavior is to activate the
+ * <SVC_HANDLER> as a "passive object." However, subclasses can
+ * override this strategy to do more sophisticated concurrency
+ * activations (such as creating the <SVC_HANDLER> as an "active
+ * object" via multi-threading or multi-processing).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ /// Factors out the code shared between the <accept> and
+ /// <handle_input> methods.
+ int shared_accept (SVC_HANDLER *svc_handler,
+ ACE_PEER_ACCEPTOR_ADDR *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle);
+
+ // = Demultiplexing hooks.
+ /// Returns the listening acceptor's <ACE_HANDLE>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Perform termination activities when <this> is removed from the
+ /// <reactor>.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Accept one connection from a client and activates the
+ /// SVC_HANDLER.
+ virtual int handle_input (ACE_HANDLE);
+
+ /// Called when an acceptor times out...
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+
+ // = Dynamic linking hooks.
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int fini (void);
+
+ /// Default version returns address info in <buf>.
+ virtual int info (ACE_TCHAR **, size_t) const;
+
+ // = Service management hooks.
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int suspend (void);
+
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int resume (void);
+
+private:
+ /**
+ * Insert ourselves into the <ACE_Reactor> so that we can continue
+ * accepting this connection asynchronously. This method should NOT
+ * be called by developers directly.
+ */
+ int register_handler (SVC_HANDLER *svc_handler,
+ const ACE_Synch_Options &options,
+ int restart);
+
+ /// Hold the svc_handler_ across asynchrony boundaries.
+ SVC_HANDLER *svc_handler_;
+
+ /// Hold the restart flag across asynchrony boundaries.
+ int restart_;
+
+ /// Factory that establishes connections passively.
+ ACE_PEER_ACCEPTOR peer_acceptor_;
+
+ /// Concurrency strategy for an Acceptor.
+ ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy_;
+
+ /// 1 if Acceptor created the concurrency strategy and thus should
+ /// delete it, else 0.
+ int delete_concurrency_strategy_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Acceptor.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Acceptor.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_ACCEPTOR_H */
diff --git a/ace/Connection/Asynch_Acceptor.cpp b/ace/Connection/Asynch_Acceptor.cpp
new file mode 100644
index 00000000000..c83faa29252
--- /dev/null
+++ b/ace/Connection/Asynch_Acceptor.cpp
@@ -0,0 +1,496 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_ASYNCH_ACCEPTOR_C
+#define ACE_ASYNCH_ACCEPTOR_C
+
+#include "ace/Asynch_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Asynch_Acceptor, "$Id$")
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_AIO_CALLS)
+// This only works on platforms that support async i/o.
+
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+
+template <class HANDLER>
+ACE_Asynch_Acceptor<HANDLER>::ACE_Asynch_Acceptor (void)
+ : listen_handle_ (ACE_INVALID_HANDLE),
+ pass_addresses_ (0),
+ validate_new_connection_ (0),
+ reissue_accept_ (1),
+ bytes_to_read_ (0)
+{
+}
+
+template <class HANDLER>
+ACE_Asynch_Acceptor<HANDLER>::~ACE_Asynch_Acceptor (void)
+{
+ // Close down the listen socket
+ if (this->listen_handle_ != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (this->listen_handle_);
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::open (const ACE_INET_Addr &address,
+ size_t bytes_to_read,
+ int pass_addresses,
+ int backlog,
+ int reuse_addr,
+ ACE_Proactor *proactor,
+ int validate_new_connection,
+ int reissue_accept,
+ int number_of_initial_accepts)
+{
+ this->proactor (proactor);
+ this->pass_addresses_ = pass_addresses;
+ this->bytes_to_read_ = bytes_to_read;
+ this->validate_new_connection_ = validate_new_connection;
+ this->reissue_accept_ = reissue_accept;
+
+ // Create the listener socket
+ this->listen_handle_ = ACE_OS::socket (address.get_type (), SOCK_STREAM, 0);
+ if (this->listen_handle_ == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_OS::socket")),
+ -1);
+ // Initialize the ACE_Asynch_Accept
+ if (this->asynch_accept_.open (*this,
+ this->listen_handle_,
+ 0,
+ this->proactor ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Asynch_Accept::open")),
+ -1);
+ if (reuse_addr)
+ {
+ // Reuse the address
+ int one = 1;
+ if (ACE_OS::setsockopt (this->listen_handle_,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (const char*) &one,
+ sizeof one) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_OS::setsockopt")),
+ -1);
+ }
+
+ // If port is not specified, bind to any port.
+ static ACE_INET_Addr sa (ACE_sap_any_cast (const ACE_INET_Addr &));
+
+ if (address == sa && ACE::bind_port (this->listen_handle_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::bind_port")),
+ -1);
+
+ // Bind to the specified port.
+ if (ACE_OS::bind (this->listen_handle_,
+ ACE_reinterpret_cast (sockaddr *,
+ address.get_addr ()),
+ address.get_size ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::bind"),
+ -1);
+
+ // Start listening.
+ if (ACE_OS::listen (this->listen_handle_, backlog) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::listen"),
+ -1);
+
+ // For the number of <intial_accepts>.
+ if (number_of_initial_accepts == -1)
+ number_of_initial_accepts = backlog;
+
+ for (int i = 0; i < number_of_initial_accepts; i++)
+ // Initiate accepts.
+ if (this->accept (bytes_to_read) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Acceptor::accept"),
+ -1);
+ return 0;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::set_handle (ACE_HANDLE listen_handle)
+{
+ // Take ownership of the <listen_handle>
+ this->listen_handle_ = listen_handle;
+
+ // Reinitialize the ACE_Asynch_Accept
+ if (this->asynch_accept_.open (*this,
+ this->listen_handle_,
+ 0,
+ this->proactor ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Asynch_Accept::open")));
+}
+
+template <class HANDLER> ACE_HANDLE
+ACE_Asynch_Acceptor<HANDLER>::get_handle (void) const
+{
+ return this->listen_handle_;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::accept (size_t bytes_to_read, const void *act)
+{
+ ACE_Message_Block *message_block = 0;
+ size_t space_needed = bytes_to_read + 2 * this->address_size ();
+
+ // Create a new message block big enough for the addresses and data
+ ACE_NEW_RETURN (message_block,
+ ACE_Message_Block (space_needed),
+ -1);
+
+ // Initiate asynchronous accepts
+ if (this->asynch_accept_.accept (*message_block,
+ bytes_to_read,
+ ACE_INVALID_HANDLE,
+ act) == -1)
+ {
+ // Cleanup on error
+ message_block->release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Asynch_Accept::accept")),
+ -1);
+ }
+ return 0;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::handle_accept (const ACE_Asynch_Accept::Result &result)
+{
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) || defined (ACE_HAS_AIO_CALLS)
+ // @@ Just debugging.
+ ACE_DEBUG ((LM_DEBUG, "%N:%l:handle_accept\n"));
+
+ // Variable for error tracking
+ int error = 0;
+
+ // If the asynchronous accept fails.
+ if (!result.success () ||
+ result.accept_handle() == ACE_INVALID_HANDLE )
+ {
+ error = 1;
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("AcceptEx")));
+ }
+
+#if !defined (ACE_HAS_AIO_CALLS)
+ // In order to use accept handle with other Window Sockets 1.1
+ // functions, we call the setsockopt function with the
+ // SO_UPDATE_ACCEPT_CONTEXT option. This option initializes the
+ // socket so that other Windows Sockets routines to access the
+ // socket correctly.
+ if (!error &&
+ ACE_OS::setsockopt (result.accept_handle (),
+ SOL_SOCKET,
+ SO_UPDATE_ACCEPT_CONTEXT,
+ (char *) &this->listen_handle_,
+ sizeof (this->listen_handle_)) == -1)
+ {
+ error = 1;
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p"),
+ ACE_LIB_TEXT ("ACE_OS::setsockopt")));
+ }
+#endif /* ACE_HAS_AIO_CALLS */
+
+ // Parse address.
+ ACE_INET_Addr local_address;
+ ACE_INET_Addr remote_address;
+ if (!error &&
+ (this->validate_new_connection_ || this->pass_addresses_))
+ // Parse the addresses.
+ this->parse_address (result,
+ remote_address,
+ local_address);
+
+ // Validate remote address
+ if (!error &&
+ this->validate_new_connection_ &&
+ this->validate_new_connection (remote_address) == -1)
+ {
+ error = 1;
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("Address validation failed")));
+ }
+
+ HANDLER *new_handler = 0;
+ if (!error)
+ {
+ // The Template method
+ new_handler = this->make_handler ();
+ if (new_handler == 0)
+ {
+ error = 1;
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("Making of new handler failed")));
+ }
+ }
+
+ // If no errors
+ if (!error)
+ {
+ // Update the Proactor.
+ new_handler->proactor (this->proactor ());
+
+ // Pass the addresses
+ if (this->pass_addresses_)
+ new_handler->addresses (remote_address,
+ local_address);
+
+ // Pass the ACT
+ if (result.act () != 0)
+ new_handler->act (result.act ());
+
+ // Set up the handler's new handle value
+ new_handler->handle (result.accept_handle ());
+
+ // Initiate the handler
+ new_handler->open (result.accept_handle (),
+ result.message_block ());
+ }
+
+ // On failure, no choice but to close the socket
+ if (error &&
+ result.accept_handle() != ACE_INVALID_HANDLE )
+ ACE_OS::closesocket (result.accept_handle ());
+
+ // Delete the dynamically allocated message_block
+ result.message_block ().release ();
+
+ // Start off another asynchronous accept to keep the backlog going
+ if (this->should_reissue_accept ())
+ this->accept (this->bytes_to_read_);
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) || defined (ACE_HAS_AIO_CALLS */
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::validate_new_connection (const ACE_INET_Addr &remote_address)
+{
+ ACE_UNUSED_ARG (remote_address);
+
+ // Default implemenation always validates the remote address.
+ return 0;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::cancel (void)
+{
+ // All I/O operations that are canceled will complete with the error
+ // ERROR_OPERATION_ABORTED. All completion notifications for the I/O
+ // operations will occur normally.
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) \
+ && ( (defined (_MSC_VER) && (_MSC_VER > 1020)) \
+ || (defined (__BORLANDC__) && (__BORLANDC__ >= 0x530)))
+ return (int) ::CancelIo (this->listen_handle_);
+#else
+ //ACE_NOTSUP_RETURN (-1);
+ // Supported now
+ return this->asynch_accept_.cancel();
+
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) && ((defined (_MSC_VER) && (_MSC_VER > 1020)) || (defined (__BORLANDC__) && (__BORLANDC__ >= 0x530))) */
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::parse_address (const
+ ACE_Asynch_Accept::Result &result,
+ ACE_INET_Addr &remote_address,
+ ACE_INET_Addr &local_address)
+{
+#if defined (ACE_HAS_AIO_CALLS)
+ // Getting the addresses.
+ sockaddr_in local_addr;
+ sockaddr_in remote_addr;
+
+ // Get the length.
+ int local_size = sizeof (local_addr);
+ int remote_size = sizeof (remote_addr);
+
+ // Get the local address.
+ if (ACE_OS::getsockname (result.accept_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ &local_addr),
+ &local_size) < 0)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Acceptor::<getsockname> failed"));
+
+ // Get the remote address.
+ if (ACE_OS::getpeername (result.accept_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ &remote_addr),
+ &remote_size) < 0)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Acceptor::<getpeername> failed"));
+
+ // Set the addresses.
+ local_address.set_addr (&local_addr, local_size);
+ remote_address.set_addr (&remote_addr, remote_size);
+
+ // @@ Just debugging.
+ char local_address_buf [BUFSIZ];
+ char remote_address_buf [BUFSIZ];
+ if (local_address.addr_to_string (local_address_buf,
+ sizeof local_address_buf) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:%p:can't obtain local_address's address string"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Asynch_Acceptor<HANDLER>::parse_address : "\
+ "Local address %s\n",
+ local_address_buf));
+
+ if (remote_address.addr_to_string (remote_address_buf,
+ sizeof remote_address_buf) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:%p:can't obtain remote_address's address string"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Asynch_Acceptor<HANDLER>::parse_address : "\
+ "Remote address %s\n",
+ remote_address_buf));
+
+#elif (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+
+ ACE_Message_Block &message_block = result.message_block ();
+
+ sockaddr *local_addr = 0;
+ sockaddr *remote_addr = 0;
+ int local_size = 0;
+ int remote_size = 0;
+
+ ::GetAcceptExSockaddrs (message_block.rd_ptr (),
+ bytes_to_read_,
+ this->address_size (),
+ this->address_size (),
+ &local_addr,
+ &local_size,
+ &remote_addr,
+ &remote_size);
+
+ local_address.set_addr (ACE_reinterpret_cast (sockaddr_in *,
+ local_addr),
+ local_size);
+ remote_address.set_addr (ACE_reinterpret_cast (sockaddr_in *,
+ remote_addr),
+ remote_size);
+#else
+ // just in case
+ errno = ENOTSUP;
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) */
+}
+
+template <class HANDLER> ACE_HANDLE
+ACE_Asynch_Acceptor<HANDLER>::handle (void) const
+{
+ return this->listen_handle_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::handle (ACE_HANDLE h)
+{
+ ACE_Handler::handle (h);
+}
+
+template <class HANDLER> ACE_Asynch_Accept &
+ACE_Asynch_Acceptor<HANDLER>::asynch_accept (void)
+{
+ return this->asynch_accept_;
+}
+
+template <class HANDLER> HANDLER *
+ACE_Asynch_Acceptor<HANDLER>::make_handler (void)
+{
+ // Default behavior
+ HANDLER *handler = 0;
+ ACE_NEW_RETURN (handler,
+ HANDLER,
+ 0);
+ return handler;
+}
+
+/* static */
+template <class HANDLER> size_t
+ACE_Asynch_Acceptor<HANDLER>::address_size (void)
+{
+ return sizeof (sockaddr) + sizeof (sockaddr_in);
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::pass_addresses (void) const
+{
+ return this->pass_addresses_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::pass_addresses (int new_value)
+{
+ this->pass_addresses_ = new_value;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::validate_new_connection (void) const
+{
+ return this->validate_new_connection_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::validate_new_connection (int new_value)
+{
+ this->validate_new_connection_ = new_value;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::reissue_accept (void) const
+{
+ return this->reissue_accept_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::reissue_accept (int new_value)
+{
+ this->reissue_accept_ = new_value;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::bytes_to_read (void) const
+{
+ return this->bytes_to_read_;
+}
+
+template <class HANDLER> void
+ACE_Asynch_Acceptor<HANDLER>::bytes_to_read (int new_value)
+{
+ this->bytes_to_read_ = new_value;
+}
+
+template <class HANDLER> int
+ACE_Asynch_Acceptor<HANDLER>::should_reissue_accept (void)
+{
+ return this->reissue_accept_;
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
+#endif /* ACE_ASYNCH_ACCEPTOR_C */
diff --git a/ace/Connection/Asynch_Acceptor.h b/ace/Connection/Asynch_Acceptor.h
new file mode 100644
index 00000000000..f2a0db738e9
--- /dev/null
+++ b/ace/Connection/Asynch_Acceptor.h
@@ -0,0 +1,202 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Asynch_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali (irfan@cs.wustl.edu)
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_ACCEPTOR_H
+#define ACE_ASYNCH_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_WIN32) || defined (ACE_HAS_AIO_CALLS)
+// This only works on platforms that support async i/o.
+
+#include "ace/Asynch_IO.h"
+
+// Forward declarations
+class ACE_Message_Block;
+class ACE_INET_Addr;
+
+/**
+ * @class ACE_Asynch_Acceptor
+ *
+ * @brief This class is an example of the Acceptor Pattern. This class
+ * will accept new connections and create new HANDLER to handle
+ * the new connections.
+ *
+ * Unlike the <ACE_Acceptor>, however, this class is designed to
+ * be used asynchronously.
+ */
+template <class HANDLER>
+class ACE_Asynch_Acceptor : public ACE_Handler
+{
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Acceptor (void);
+
+ /// Virtual destruction
+ virtual ~ACE_Asynch_Acceptor (void);
+
+ /**
+ * This starts the listening process at the port specified by
+ * <address>. ACE_Asynch_Acceptor initiates the AcceptEx calls with
+ * <bytes_to_read>. The buffer for the initial data will be created
+ * by ACE_Asynch_Acceptor. This buffer will be passed to the
+ * handler in the <ACE_Service_Handler::open> callback. If this
+ * buffer is required past the <open> callback, the
+ * ACE_Service_Handler must copy the data. If the <pass_addresses>
+ * flag is set, ACE_Asynch_Acceptor will call
+ * <ACE_Service_Handler::addresses> before calling
+ * <ACE_Service_Handler::open>. The <backlog> parameter specifies
+ * the listen backlog and the outstanding AcceptEx calls.
+ * <number_of_initial_accepts> is the number of asynchronous accepts
+ * that are started at the end of <open>. If
+ * <number_of_initial_accepts> is -1, then
+ * <number_of_initial_accepts> is set to <backlog> and hence
+ * <backlog> number of asynchronous accepts are started.
+ */
+ virtual int open (const ACE_INET_Addr &address,
+ size_t bytes_to_read = 0,
+ int pass_addresses = 0,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int reuse_addr = 1,
+ ACE_Proactor *proactor = 0,
+ int validate_new_connection = 0,
+ int reissue_accept = 1,
+ int number_of_initial_accepts = -1);
+
+ /// Get the underlying handle.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /**
+ * Set the underlying listen handle. It is the user's responsibility
+ * to make sure that the old listen handle has been appropriately
+ * closed and the all outstanding asynchronous operations have
+ * either completed or have been canceled on the old listen handle.
+ */
+ virtual void set_handle (ACE_HANDLE handle);
+
+ /// This initiates a new asynchronous accept through the <AcceptEx>
+ /// call.
+ virtual int accept (size_t bytes_to_read = 0, const void *act = 0);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread.
+ * Windows NT- The function does not cancel accept operations
+ * issued by other threads
+ * POSIX - all OK, it delegates cancelation to the
+ * ACE_POSIX_Asynch_Accept
+ *
+ */
+ virtual int cancel (void);
+
+ /**
+ * Template method for address validation.
+ *
+ * Default implemenation always validates the remote address.
+ */
+ virtual int validate_new_connection (const ACE_INET_Addr &remote_address);
+
+ /**
+ * Template method for deciding whether to reissue accept.
+ *
+ * Default implemenation always returns this->reissue_accept_.
+ */
+ virtual int should_reissue_accept (void);
+
+ //
+ // These are low level tweaking methods
+ //
+
+ /// Set and get flag that indicates if parsing and passing of
+ /// addresses to the service_handler is necessary.
+ virtual int pass_addresses (void) const;
+ virtual void pass_addresses (int new_value);
+
+ /// Set and get flag that indicates if address validation is
+ /// required.
+ virtual int validate_new_connection (void) const;
+ virtual void validate_new_connection (int new_value);
+
+ /// Set and get flag that indicates if a new accept should be
+ /// reissued when a accept completes.
+ virtual int reissue_accept (void) const;
+ virtual void reissue_accept (int new_value);
+
+ /// Set and get bytes to be read with the <accept> call.
+ virtual int bytes_to_read (void) const;
+ virtual void bytes_to_read (int new_value);
+
+ /// This is required by the AcceptEx call.
+ static size_t address_size (void);
+
+protected:
+
+ /// This is called when an outstanding accept completes.
+ virtual void handle_accept (const ACE_Asynch_Accept::Result &result);
+
+ /// Return the listen handle.
+ ACE_HANDLE handle (void) const;
+ /// Set the listen handle.
+ void handle (ACE_HANDLE h);
+
+ /// This parses the address from read buffer.
+ void parse_address (const ACE_Asynch_Accept::Result &result,
+ ACE_INET_Addr &remote_address,
+ ACE_INET_Addr &local_address);
+
+ /// Return the asynch accept object.
+ ACE_Asynch_Accept &asynch_accept (void);
+
+ /**
+ * This is the template method used to create new handler.
+ * Subclasses must overwrite this method if a new handler creation
+ * strategy is required.
+ */
+ virtual HANDLER *make_handler (void);
+
+private:
+ /// Handle used to listen for new connections.
+ ACE_HANDLE listen_handle_;
+
+ /// <Asynch_Accept> used to make life easier :-)
+ ACE_Asynch_Accept asynch_accept_;
+
+ /// Flag that indicates if parsing of addresses is necessary.
+ int pass_addresses_;
+
+ /// Flag that indicates if address validation is required.
+ int validate_new_connection_;
+
+ /// Flag that indicates if a new accept should be reissued when a
+ /// accept completes.
+ int reissue_accept_;
+
+ /// Bytes to be read with the <accept> call.
+ int bytes_to_read_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Asynch_Acceptor.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Asynch_Acceptor.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
+#include "ace/post.h"
+#endif /* ACE_ASYNCH_ACCEPTOR_H */
diff --git a/ace/Connection/Asynch_IO.cpp b/ace/Connection/Asynch_IO.cpp
new file mode 100644
index 00000000000..4fa2b269a90
--- /dev/null
+++ b/ace/Connection/Asynch_IO.cpp
@@ -0,0 +1,1276 @@
+// $Id$
+
+#include "ace/Asynch_IO.h"
+
+ACE_RCSID(ace, Asynch_IO, "$Id$")
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+// This only works on platforms with Asynchronous IO
+
+#include "ace/Proactor.h"
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+#include "ace/Asynch_IO_Impl.h"
+
+u_long
+ACE_Asynch_Result::bytes_transferred (void) const
+{
+ return this->implementation ()->bytes_transferred ();
+}
+
+const void *
+ACE_Asynch_Result::act (void) const
+{
+ return this->implementation ()->act ();
+}
+
+int
+ACE_Asynch_Result::success (void) const
+{
+ return this->implementation ()->success ();
+}
+
+const void *
+ACE_Asynch_Result::completion_key (void) const
+{
+ return this->implementation ()->completion_key ();
+}
+
+u_long
+ACE_Asynch_Result::error (void) const
+{
+ return this->implementation ()->error ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Result::event (void) const
+{
+ return this->implementation ()->event ();
+}
+
+u_long
+ACE_Asynch_Result::offset (void) const
+{
+ return this->implementation ()->offset ();
+}
+
+u_long
+ACE_Asynch_Result::offset_high (void) const
+{
+ return this->implementation ()->offset_high ();
+}
+
+int
+ACE_Asynch_Result::priority (void) const
+{
+ return this->implementation ()->priority ();
+}
+
+int
+ACE_Asynch_Result::signal_number (void) const
+{
+ return this->implementation ()->signal_number ();
+}
+
+ACE_Asynch_Result::ACE_Asynch_Result (ACE_Asynch_Result_Impl *implementation)
+ : implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Result::~ACE_Asynch_Result (void)
+{
+ // Proactor deletes the implementation when the <complete> finishes.
+}
+
+ACE_Asynch_Result_Impl *
+ACE_Asynch_Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// *********************************************************************
+
+int
+ACE_Asynch_Operation::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return this->implementation ()->open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Operation::cancel (void)
+{
+ return this->implementation ()->cancel ();
+}
+
+ACE_Proactor *
+ACE_Asynch_Operation::proactor (void) const
+{
+ return this->implementation ()->proactor ();
+}
+
+ACE_Asynch_Operation_Impl *
+ACE_Asynch_Operation::implementation (void) const
+{
+ return this->implementation_;
+}
+
+ACE_Asynch_Operation::ACE_Asynch_Operation (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Operation::~ACE_Asynch_Operation (void)
+{
+ delete this->implementation_;
+ this->implementation_ = 0;
+}
+
+void
+ACE_Asynch_Operation::implementation (ACE_Asynch_Operation_Impl *implementation)
+{
+ this->implementation_ = implementation;
+}
+
+ACE_Proactor *
+ACE_Asynch_Operation::get_proactor (ACE_Proactor *user_proactor,
+ ACE_Handler &handler) const
+{
+ if (user_proactor == 0)
+ {
+ // Grab the singleton proactor if <handler->proactor> is zero
+ user_proactor = handler.proactor ();
+ if (user_proactor == 0)
+ user_proactor = ACE_Proactor::instance ();
+ }
+
+ return user_proactor;
+}
+
+// ************************************************************
+
+ACE_Asynch_Read_Stream::ACE_Asynch_Read_Stream (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Read_Stream::~ACE_Asynch_Read_Stream (void)
+{
+}
+
+int
+ACE_Asynch_Read_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Read_Stream_Impl *implementation = proactor->create_asynch_read_stream ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->read (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Read_Stream_Impl *
+ACE_Asynch_Read_Stream::implementation (void) const
+{
+ return implementation_;
+}
+
+void
+ACE_Asynch_Read_Stream::implementation (ACE_Asynch_Read_Stream_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Init the base class' implementation also.
+ ACE_Asynch_Operation::implementation (this->implementation_);
+}
+
+// ************************************************************
+
+u_long
+ACE_Asynch_Read_Stream::Result::bytes_to_read (void) const
+{
+ return this->implementation ()->bytes_to_read ();
+}
+
+ACE_Message_Block &
+ACE_Asynch_Read_Stream::Result::message_block (void) const
+{
+ return this->implementation ()->message_block ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Read_Stream::Result::handle (void) const
+{
+ return this->implementation ()->handle ();
+}
+
+ACE_Asynch_Read_Stream::Result::Result (ACE_Asynch_Read_Stream_Result_Impl *implementation)
+ : ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Read_Stream::Result::~Result (void)
+{
+ // Proactor will delete the implementation after <complete> is
+ // finished.
+}
+
+ACE_Asynch_Read_Stream_Result_Impl *
+ACE_Asynch_Read_Stream::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ***************************************************
+
+ACE_Asynch_Write_Stream::ACE_Asynch_Write_Stream (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Write_Stream::~ACE_Asynch_Write_Stream (void)
+{
+}
+
+int
+ACE_Asynch_Write_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Write_Stream_Impl *implementation = proactor->create_asynch_write_stream ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->write (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Write_Stream_Impl *
+ACE_Asynch_Write_Stream::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Write_Stream::implementation (ACE_Asynch_Write_Stream_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Init the base class' implementation also.
+ ACE_Asynch_Operation::implementation (this->implementation_);
+}
+
+// ************************************************************
+
+u_long
+ACE_Asynch_Write_Stream::Result::bytes_to_write (void) const
+{
+ return this->implementation ()->bytes_to_write ();
+}
+
+ACE_Message_Block &
+ACE_Asynch_Write_Stream::Result::message_block (void) const
+{
+ return this->implementation ()->message_block ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Write_Stream::Result::handle (void) const
+{
+ return this->implementation ()->handle ();
+}
+
+ACE_Asynch_Write_Stream::Result::Result (ACE_Asynch_Write_Stream_Result_Impl *implementation)
+ : ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Write_Stream::Result::~Result (void)
+{
+ // Proactor will delte the implementation when the <complete> call
+ // finishes.
+}
+
+ACE_Asynch_Write_Stream_Result_Impl *
+ACE_Asynch_Write_Stream::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+ACE_Asynch_Read_File::ACE_Asynch_Read_File (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Read_File::~ACE_Asynch_Read_File (void)
+{
+}
+
+int
+ACE_Asynch_Read_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Read_File_Impl *implementation = proactor->create_asynch_read_file ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->read (message_block,
+ bytes_to_read,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Read_File_Impl *
+ACE_Asynch_Read_File::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Read_File::implementation (ACE_Asynch_Read_File_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Set also the base class' implementation.
+ ACE_Asynch_Read_Stream::implementation (implementation);
+}
+
+// ************************************************************
+
+ACE_Asynch_Read_File::Result::Result (ACE_Asynch_Read_File_Result_Impl *implementation)
+ : ACE_Asynch_Read_Stream::Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Read_File::Result::~Result (void)
+{
+ // Proactor will delete the implementation when <complete> call
+ // completes.
+}
+
+ACE_Asynch_Read_File_Result_Impl *
+ACE_Asynch_Read_File::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+ACE_Asynch_Write_File::ACE_Asynch_Write_File (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Write_File::~ACE_Asynch_Write_File (void)
+{
+}
+
+int
+ACE_Asynch_Write_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Write_File_Impl *implementation = proactor->create_asynch_write_file ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->write (message_block,
+ bytes_to_write,
+ offset,
+ offset_high,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Write_File_Impl *
+ACE_Asynch_Write_File::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Write_File::implementation (ACE_Asynch_Write_File_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Init the base class' implementation also.
+ ACE_Asynch_Write_Stream::implementation (implementation);
+}
+
+// ************************************************************
+
+ACE_Asynch_Write_File::Result::Result (ACE_Asynch_Write_File_Result_Impl *implementation)
+ : ACE_Asynch_Write_Stream::Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Write_File::Result::~Result (void)
+{
+ // Proactor will delete the implementation when the <complete> call
+ // completes.
+}
+
+ACE_Asynch_Write_File_Result_Impl *
+ACE_Asynch_Write_File::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// *********************************************************************
+
+ACE_Asynch_Accept::ACE_Asynch_Accept (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Accept::~ACE_Asynch_Accept (void)
+{
+}
+
+int
+ACE_Asynch_Accept::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Accept_Impl *implementation = proactor->create_asynch_accept ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Accept::accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->accept (message_block,
+ bytes_to_read,
+ accept_handle,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Accept_Impl *
+ACE_Asynch_Accept::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Accept::implementation (ACE_Asynch_Accept_Impl *implementation)
+{
+ this->implementation_ = implementation;
+ // Set the implementation in the base class.
+ ACE_Asynch_Operation::implementation (implementation);
+}
+
+// ************************************************************
+
+u_long
+ACE_Asynch_Accept::Result::bytes_to_read (void) const
+{
+ return this->implementation ()->bytes_to_read ();
+}
+
+ACE_Message_Block &
+ACE_Asynch_Accept::Result::message_block (void) const
+{
+ return this->implementation ()->message_block ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Accept::Result::listen_handle (void) const
+{
+ return this->implementation ()->listen_handle ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Accept::Result::accept_handle (void) const
+{
+ return this->implementation ()->accept_handle ();
+}
+
+ACE_Asynch_Accept::Result::Result (ACE_Asynch_Accept_Result_Impl *implementation)
+ : ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Accept::Result::~Result (void)
+{
+ // Proactor will delete the implementation when the <complete> call
+ // completes.
+}
+
+ACE_Asynch_Accept_Result_Impl *
+ACE_Asynch_Accept::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+ACE_Asynch_Transmit_File::ACE_Asynch_Transmit_File (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Transmit_File::~ACE_Asynch_Transmit_File (void)
+{
+}
+
+int
+ACE_Asynch_Transmit_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Transmit_File_Impl *implementation = proactor->create_asynch_transmit_file ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
+ Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->transmit_file (file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Transmit_File_Impl *
+ACE_Asynch_Transmit_File::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Transmit_File::implementation (ACE_Asynch_Transmit_File_Impl *implementation)
+{
+ this->implementation_ = implementation;
+ // Set the base class' implementation also.
+ ACE_Asynch_Operation::implementation (this->implementation_);
+}
+
+// ***********************************************************************************
+
+ACE_HANDLE
+ACE_Asynch_Transmit_File::Result::socket (void) const
+{
+ return this->implementation ()->socket ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Transmit_File::Result::file (void) const
+{
+ return this->implementation ()->file ();
+}
+
+ACE_Asynch_Transmit_File::Header_And_Trailer *
+ACE_Asynch_Transmit_File::Result::header_and_trailer (void) const
+{
+ return this->implementation ()->header_and_trailer ();
+}
+
+u_long
+ACE_Asynch_Transmit_File::Result::bytes_to_write (void) const
+{
+ return this->implementation ()->bytes_to_write ();
+}
+
+u_long
+ACE_Asynch_Transmit_File::Result::bytes_per_send (void) const
+{
+ return this->implementation ()->bytes_per_send ();
+}
+
+u_long
+ACE_Asynch_Transmit_File::Result::flags (void) const
+{
+ return this->implementation ()->flags ();
+}
+
+ACE_Asynch_Transmit_File::Result::Result (ACE_Asynch_Transmit_File_Result_Impl *implementation)
+ : ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Transmit_File::Result::~Result (void)
+{
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_Asynch_Transmit_File::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+ACE_Asynch_Transmit_File::Header_And_Trailer::Header_And_Trailer (ACE_Message_Block *header,
+ u_long header_bytes,
+ ACE_Message_Block *trailer,
+ u_long trailer_bytes)
+ : header_ (header),
+ header_bytes_ (header_bytes),
+ trailer_ (trailer),
+ trailer_bytes_ (trailer_bytes)
+{
+}
+
+ACE_Asynch_Transmit_File::Header_And_Trailer::~Header_And_Trailer (void)
+{
+}
+
+void
+ACE_Asynch_Transmit_File::Header_And_Trailer::header_and_trailer (ACE_Message_Block *header,
+ u_long header_bytes,
+ ACE_Message_Block *trailer,
+ u_long trailer_bytes)
+{
+ this->header (header);
+ this->header_bytes (header_bytes);
+ this->trailer (trailer);
+ this->trailer_bytes (trailer_bytes);
+}
+
+ACE_Message_Block *
+ACE_Asynch_Transmit_File::Header_And_Trailer::header (void) const
+{
+ return this->header_;
+}
+
+void
+ACE_Asynch_Transmit_File::Header_And_Trailer::header (ACE_Message_Block *message_block)
+{
+ this->header_ = message_block;
+}
+
+u_long
+ACE_Asynch_Transmit_File::Header_And_Trailer::header_bytes (void) const
+{
+ return this->header_bytes_;
+}
+
+void
+ACE_Asynch_Transmit_File::Header_And_Trailer::header_bytes (u_long bytes)
+{
+ this->header_bytes_ = bytes;
+}
+
+ACE_Message_Block *
+ACE_Asynch_Transmit_File::Header_And_Trailer::trailer (void) const
+{
+ return this->trailer_;
+}
+
+void
+ACE_Asynch_Transmit_File::Header_And_Trailer::trailer (ACE_Message_Block *message_block)
+{
+ this->trailer_ = message_block;
+}
+
+u_long
+ACE_Asynch_Transmit_File::Header_And_Trailer::trailer_bytes (void) const
+{
+ return this->trailer_bytes_;
+}
+
+void
+ACE_Asynch_Transmit_File::Header_And_Trailer::trailer_bytes (u_long bytes)
+{
+ this->trailer_bytes_ = bytes;
+}
+
+ACE_LPTRANSMIT_FILE_BUFFERS
+ACE_Asynch_Transmit_File::Header_And_Trailer::transmit_buffers (void)
+{
+ // If both are zero, return zero
+ if (this->header_ == 0 && this->trailer_ == 0)
+ return 0;
+ else
+ {
+ // Something is valid
+
+ // If header is valid, set the fields
+ if (this->header_ != 0)
+ {
+ this->transmit_buffers_.Head = this->header_->rd_ptr ();
+ this->transmit_buffers_.HeadLength = this->header_bytes_;
+ }
+ else
+ {
+ this->transmit_buffers_.Head = 0;
+ this->transmit_buffers_.HeadLength = 0;
+ }
+
+ // If trailer is valid, set the fields
+ if (this->trailer_ != 0)
+ {
+ this->transmit_buffers_.Tail = this->trailer_->rd_ptr ();
+ this->transmit_buffers_.TailLength = this->trailer_bytes_;
+ }
+ else
+ {
+ this->transmit_buffers_.Tail = 0;
+ this->transmit_buffers_.TailLength = 0;
+ }
+
+ // Return the transmit buffers
+ return &this->transmit_buffers_;
+ }
+}
+
+// *********************************************************************
+
+ACE_Handler::ACE_Handler (void)
+ : proactor_ (0), handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+ACE_Handler::ACE_Handler (ACE_Proactor *d)
+ : proactor_ (d), handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+ACE_Handler::~ACE_Handler (void)
+{
+}
+
+void
+ACE_Handler::handle_read_stream (const ACE_Asynch_Read_Stream::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_write_stream (const ACE_Asynch_Write_Stream::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_write_dgram (const ACE_Asynch_Write_Dgram::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_read_dgram (const ACE_Asynch_Read_Dgram::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_accept (const ACE_Asynch_Accept::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_transmit_file (const ACE_Asynch_Transmit_File::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_read_file (const ACE_Asynch_Read_File::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_write_file (const ACE_Asynch_Write_File::Result & /* result */)
+{
+}
+
+void
+ACE_Handler::handle_time_out (const ACE_Time_Value & /* tv */,
+ const void * /* act */)
+{
+}
+
+void
+ACE_Handler::handle_wakeup (void)
+{
+}
+
+ACE_Proactor *
+ACE_Handler::proactor (void)
+{
+ return this->proactor_;
+}
+
+void
+ACE_Handler::proactor (ACE_Proactor *p)
+{
+ this->proactor_ = p;
+}
+
+ACE_HANDLE
+ACE_Handler::handle (void) const
+{
+ return this->handle_;
+}
+
+void
+ACE_Handler::handle (ACE_HANDLE h)
+{
+ this->handle_ = h;
+}
+
+// ************************************************************
+
+ACE_Service_Handler::ACE_Service_Handler (void)
+{
+}
+
+ACE_Service_Handler::~ACE_Service_Handler (void)
+{
+}
+
+void
+ACE_Service_Handler::addresses (const ACE_INET_Addr &remote_address,
+ const ACE_INET_Addr &local_address)
+{
+ // Default behavior is to print out the addresses.
+ ACE_TCHAR local_address_buf[BUFSIZ], remote_address_buf[BUFSIZ];
+ if (local_address.addr_to_string (local_address_buf, sizeof local_address_buf) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("can't obtain local_address's address string")));
+
+ if (remote_address.addr_to_string (remote_address_buf, sizeof remote_address_buf) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("can't obtain remote_address's address string")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("On fd %d\n"), this->handle ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("local address %s\n"), local_address_buf));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("remote address %s\n"), remote_address_buf));
+}
+
+void
+ACE_Service_Handler::act (const void *)
+{
+}
+
+void
+ACE_Service_Handler::open (ACE_HANDLE,
+ ACE_Message_Block &)
+{
+}
+
+
+// ************************************************************
+
+ACE_Asynch_Read_Dgram::ACE_Asynch_Read_Dgram (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Read_Dgram::~ACE_Asynch_Read_Dgram (void)
+{
+}
+
+int
+ACE_Asynch_Read_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Read_Dgram_Impl *implementation = proactor->create_asynch_read_dgram ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+ssize_t
+ACE_Asynch_Read_Dgram::recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->recv (message_block,
+ number_of_bytes_recvd,
+ flags,
+ protocol_family,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Read_Dgram_Impl *
+ACE_Asynch_Read_Dgram::implementation (void) const
+{
+ return implementation_;
+}
+
+void
+ACE_Asynch_Read_Dgram::implementation (ACE_Asynch_Read_Dgram_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Init the bas class' implementation also.
+ ACE_Asynch_Operation::implementation(this->implementation_);
+}
+
+// ************************************************************
+
+int
+ACE_Asynch_Read_Dgram::Result::remote_address (ACE_Addr& addr) const
+{
+ return this->implementation ()->remote_address (addr);
+}
+
+ACE_Message_Block*
+ACE_Asynch_Read_Dgram::Result::message_block (void) const
+{
+ return this->implementation ()->message_block ();
+}
+
+int
+ACE_Asynch_Read_Dgram::Result::flags (void) const
+{
+ return this->implementation ()->flags ();
+}
+
+u_long
+ACE_Asynch_Read_Dgram::Result::bytes_to_read (void) const
+{
+ return this->implementation ()->bytes_to_read ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Read_Dgram::Result::handle (void) const
+{
+ return this->implementation ()->handle();
+}
+
+ACE_Asynch_Read_Dgram::Result::Result (ACE_Asynch_Read_Dgram_Result_Impl *implementation)
+: ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Read_Dgram::Result::~Result (void)
+{
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl *
+ACE_Asynch_Read_Dgram::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+// ************************************************************
+
+
+ACE_Asynch_Write_Dgram::ACE_Asynch_Write_Dgram (void)
+ : implementation_ (0)
+{
+}
+
+ACE_Asynch_Write_Dgram::~ACE_Asynch_Write_Dgram (void)
+{
+}
+
+int
+ACE_Asynch_Write_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // Get a proactor for/from the user.
+ proactor = this->get_proactor (proactor, handler);
+
+ // Delete the old implementation.
+ delete this->implementation_;
+ this->implementation_ = 0;
+
+ // Now let us get the implementation initialized.
+ ACE_Asynch_Write_Dgram_Impl *implementation = proactor->create_asynch_write_dgram ();
+ if (implementation == 0)
+ return -1;
+
+ // Set the implementation class
+ this->implementation (implementation);
+
+ // Call the <open> method of the base class.
+ return ACE_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+ssize_t
+ACE_Asynch_Write_Dgram::send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr& remote_addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->send (message_block,
+ number_of_bytes_sent,
+ flags,
+ remote_addr,
+ act,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Write_Dgram_Impl *
+ACE_Asynch_Write_Dgram::implementation (void) const
+{
+ return this->implementation_;
+}
+
+void
+ACE_Asynch_Write_Dgram::implementation (ACE_Asynch_Write_Dgram_Impl *implementation)
+{
+ this->implementation_ = implementation;
+
+ // Init the base class' implementation also.
+ ACE_Asynch_Operation::implementation (this->implementation_);
+}
+
+// ************************************************************
+
+u_long
+ACE_Asynch_Write_Dgram::Result::bytes_to_write (void) const
+{
+ return this->implementation ()->bytes_to_write ();
+}
+
+ACE_Message_Block*
+ACE_Asynch_Write_Dgram::Result::message_block () const
+{
+ return this->implementation ()->message_block ();
+}
+
+int
+ACE_Asynch_Write_Dgram::Result::flags (void) const
+{
+ return this->implementation ()->flags ();
+}
+
+ACE_HANDLE
+ACE_Asynch_Write_Dgram::Result::handle (void) const
+{
+ return this->implementation ()->handle ();
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl *
+ACE_Asynch_Write_Dgram::Result::implementation (void) const
+{
+ return this->implementation_;
+}
+
+ACE_Asynch_Write_Dgram::Result::Result (ACE_Asynch_Write_Dgram_Result_Impl *implementation)
+: ACE_Asynch_Result (implementation),
+ implementation_ (implementation)
+{
+}
+
+ACE_Asynch_Write_Dgram::Result::~Result (void)
+{
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
diff --git a/ace/Connection/Asynch_IO.h b/ace/Connection/Asynch_IO.h
new file mode 100644
index 00000000000..311650d33ee
--- /dev/null
+++ b/ace/Connection/Asynch_IO.h
@@ -0,0 +1,1441 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Asynch_IO.h
+ *
+ * $Id$
+ *
+ * This works on Win32 (#if defined (ACE_WIN32) && !defined
+ * (ACE_HAS_WINCE)) platforms and on POSIX4 platforms with <aio_*>
+ * routines (#if defined (ACE_HAS_AIO_CALLS))
+ *
+ * On Win32 platforms, the implementation of
+ * <ACE_Asynch_Transmit_File> and <ACE_Asynch_Accept> are only
+ * supported if ACE_HAS_WINSOCK2 is defined or you are on WinNT 4.0
+ * or higher.
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_IO_H
+#define ACE_ASYNCH_IO_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+
+// Forward declarations
+class ACE_Proactor;
+class ACE_Handler;
+class ACE_Message_Block;
+class ACE_INET_Addr;
+
+// Forward declarations
+class ACE_Asynch_Result_Impl;
+
+/**
+ * @class ACE_Asynch_Result
+ *
+ * @brief An interface base class which allows users access to common
+ * information related to an asynchronous operation.
+ *
+ * An interface base class from which you can obtain some basic
+ * information like the number of bytes transferred, the ACT
+ * associated with the asynchronous operation, indication of
+ * success or failure, etc. Subclasses may want to store more
+ * information that is particular to the asynchronous operation
+ * it represents.
+ */
+class ACE_Export ACE_Asynch_Result
+{
+
+public:
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * On WIN32, this returns the ACT associated with the handle when it
+ * was registered with the I/O completion port.
+ *
+ * @@ This is not implemented for POSIX4 platforms. Returns 0.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fails.
+ u_long error (void) const;
+
+ /**
+ * On WIN32, this returns the event associated with the OVERLAPPED
+ * structure.
+ *
+ * This returns ACE_INVALID_HANDLE on POSIX4-Unix platforms.
+ */
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really makes sense only when doing file I/O.
+ *
+ * On WIN32, these are represented in the OVERLAPPED datastructure.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /**
+ * Priority of the operation.
+ *
+ * On POSIX4-Unix, this is supported. Priority works like <nice> in
+ * Unix. Negative values are not allowed. 0 means priority of the
+ * operation same as the process priority. 1 means priority of the
+ * operation is one less than process. And so forth.
+ *
+ * On Win32, this is a no-op.
+ */
+ int priority (void) const;
+
+ /**
+ * POSIX4 real-time signal number to be used for the
+ * operation. <signal_number> ranges from ACE_SIGRTMIN to ACE_SIGRTMAX. By
+ * default, ACE_SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Result (void);
+
+protected:
+ /// Constructor. This implementation will not be deleted. The
+ /// implementation will be deleted by the Proactor.
+ ACE_Asynch_Result (ACE_Asynch_Result_Impl *implementation);
+
+ /// Get the implementation class.
+ ACE_Asynch_Result_Impl *implementation (void) const;
+
+ /// Implementation class.
+ ACE_Asynch_Result_Impl *implementation_;
+};
+
+// Forward declarations
+class ACE_Asynch_Operation_Impl;
+
+/**
+ * @class ACE_Asynch_Operation
+ *
+ * @brief This is an interface base class for all asynch
+ * operations. The resposiblility of this class is to forward
+ * all methods to its delegation/implementation class, e.g.,
+ * <ACE_WIN32_Asynch_Operation> or <ACE_POSIX_Asynch_Operation>.
+ *
+ * There are some attributes and functionality which is common
+ * to all asychronous operations. The delegation classes of this
+ * class will factor out this code.
+ */
+class ACE_Export ACE_Asynch_Operation
+{
+
+public:
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * (Attempts to) cancel the asynchronous operation pending against
+ * the <handle> registered with this Operation.
+ *
+ * All completion notifications for the I/O operations will occur
+ * normally.
+ *
+ * = Return Values:
+ *
+ * -1 : Operation failed. (can get only in POSIX).
+ * 0 : All the operations were cancelled.
+ * 1 : All the operations were already finished in this
+ * handle. Unable to cancel them.
+ * 2 : Atleast one of the requested operations cannot be
+ * cancelled.
+ *
+ * There is slight difference in the semantics between NT and POSIX
+ * platforms which is given below.
+ *
+ * = Win32 :
+ *
+ * cancels all pending accepts operations that were issued by the
+ * calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ * All I/O operations that are canceled will complete with the
+ * error ERROR_OPERATION_ABORTED.
+ *
+ * = POSIX:
+ *
+ * Attempts to cancel one or more asynchronous I/O requests
+ * currently outstanding against the <handle> registered in this
+ * operation.
+ * For requested operations that are successfully canceled, the
+ * associated error status is set to ECANCELED.
+ */
+ int cancel (void);
+
+
+ // = Access methods.
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Operation (void);
+
+protected:
+ /// Constructor.
+ ACE_Asynch_Operation (void);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Operation_Impl *implementation (void) const;
+
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Operation_Impl *implementation);
+
+ /// Get a proactor for/from the user
+ ACE_Proactor *get_proactor (ACE_Proactor *user_proactor,
+ ACE_Handler &handler) const;
+
+ /// Implementation class.
+ ACE_Asynch_Operation_Impl *implementation_;
+};
+
+// Forward declarations
+class ACE_Asynch_Read_Stream_Result_Impl;
+class ACE_Asynch_Read_Stream_Impl;
+
+/**
+ * @class ACE_Asynch_Read_Stream
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a stream. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can
+ * started using this class. An ACE_Asynch_Read_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_stream>
+ * callback.
+ */
+class ACE_Export ACE_Asynch_Read_Stream : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Read_Stream (void);
+
+ /// Destructor
+ virtual ~ACE_Asynch_Read_Stream (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous read. Upto <bytes_to_read> will
+ * be read and stored in the <message_block>. <message_block>'s
+ * <wr_ptr> will be updated to reflect the added bytes if the read
+ * operation is successful completed. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, <priority> is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long num_bytes_to_read,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Read_Stream_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Read_Stream_Impl *implementation);
+
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Read_Stream_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is the class which will be passed back to the
+ * <handler> when the asynchronous read completes. This class
+ * forwards all the methods to the implementation classes.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous read.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Read_Stream_Result;
+ friend class ACE_WIN32_Asynch_Read_Stream_Result;
+
+ public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ /// Get the implementation class.
+ ACE_Asynch_Read_Stream_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constructor.
+ Result (ACE_Asynch_Read_Stream_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// The implementation class.
+ ACE_Asynch_Read_Stream_Result_Impl *implementation_;
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Write_Stream_Impl;
+class ACE_Asynch_Write_Stream_Result_Impl;
+
+/**
+ * @class ACE_Asynch_Write_Stream
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a stream. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <writes>s can
+ * started using this class. An ACE_Asynch_Write_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * write completes through the
+ * <ACE_Handler::handle_write_stream> callback.
+ */
+class ACE_Export ACE_Asynch_Write_Stream : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Write_Stream (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Write_Stream (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous write. Upto <bytes_to_write>
+ * will be written from the <message_block>. Upon successful completion
+ * of the write operation, <message_block>'s <rd_ptr> is updated to
+ * reflect the data that was written. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this argument is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Write_Stream_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Write_Stream_Impl *implementation);
+
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Write_Stream_Impl *implementation_;
+
+public:
+/**
+ * @class
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous write completes. This class
+ * forwards all the methods to the implementation class.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Write_Stream_Result;
+ friend class ACE_WIN32_Asynch_Write_Stream_Result;
+
+ public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ /// Get the implementation class.
+ ACE_Asynch_Write_Stream_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constrcutor.
+ Result (ACE_Asynch_Write_Stream_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// Implementation class.
+ ACE_Asynch_Write_Stream_Result_Impl *implementation_;
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Read_File_Impl;
+class ACE_Asynch_Read_File_Result_Impl;
+
+/**
+ * @class ACE_Asynch_Read_File
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a file. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can
+ * started using this class. An ACE_Asynch_Read_File::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_file>
+ * callback.
+ * This class differs slightly from ACE_Asynch_Read_Stream as it
+ * allows the user to specify an offset for the read.
+ */
+class ACE_Export ACE_Asynch_Read_File : public ACE_Asynch_Read_Stream
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Read_File (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Read_File (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous read. Upto <bytes_to_read> will
+ * be read and stored in the <message_block>. The read will start
+ * at <offset> from the beginning of the file. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this argument is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset = 0,
+ u_long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Read_File_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Read_File_Impl *implementation);
+
+ /// Delegation/implementation class that all methods will be
+ /// forwarded to.
+ ACE_Asynch_Read_File_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous read completes. This class
+ * forwards all the methods to the implementation class.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous read.
+ * This class differs slightly from
+ * ACE_Asynch_Read_Stream::Result as it calls back
+ * <ACE_Handler::handle_read_file> on the <handler> instead of
+ * <ACE_Handler::handle_read_stream>. No additional state is
+ * required by this class as ACE_Asynch_Result can store the
+ * <offset>.
+ */
+ class ACE_Export Result : public ACE_Asynch_Read_Stream::Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Read_File_Result;
+ friend class ACE_WIN32_Asynch_Read_File_Result;
+
+ public:
+ /// Get the implementation class.
+ ACE_Asynch_Read_File_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constructor. This implementation will not be deleted.
+ Result (ACE_Asynch_Read_File_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// The implementation class.
+ ACE_Asynch_Read_File_Result_Impl *implementation_;
+
+ private:
+ /// Here just to provide an dummpy implementation, since the
+ /// one auto generated by MSVC is flagged as infinitely recursive
+ void operator= (Result &) {}
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Write_File_Impl;
+class ACE_Asynch_Write_File_Result_Impl;
+
+/**
+ * @class ACE_Asynch_Write_File
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a file. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <write>s can be
+ * started using this class. A ACE_Asynch_Write_File::Result
+ * will be passed back to the <handler> when the asynchronous
+ * writes completes through the <ACE_Handler::handle_write_file>
+ * callback.
+ * This class differs slightly from ACE_Asynch_Write_Stream as
+ * it allows the user to specify an offset for the write.
+ */
+class ACE_Export ACE_Asynch_Write_File : public ACE_Asynch_Write_Stream
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Write_File (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Write_File (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous write. Upto <bytes_to_write>
+ * will be written from the <message_block>, starting at the
+ * block's <rd_ptr>. The write will go to the file, starting
+ * <offset> bytes from the beginning of the file. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset = 0,
+ u_long offset_high = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Write_File_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation.
+ void implementation (ACE_Asynch_Write_File_Impl *implementation);
+
+ /// Implementation object.
+ ACE_Asynch_Write_File_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous write completes. This class
+ * forwards all the methods to the implementation class.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ * This class differs slightly from
+ * ACE_Asynch_Write_Stream::Result as it calls back
+ * <ACE_Handler::handle_write_file> on the <handler> instead
+ * of <ACE_Handler::handle_write_stream>. No additional state
+ * is required by this class as ACE_Asynch_Result can store
+ * the <offset>.
+ */
+ class ACE_Export Result : public ACE_Asynch_Write_Stream::Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Write_File_Result;
+ friend class ACE_WIN32_Asynch_Write_File_Result;
+
+ public:
+ /// Get the implementation class.
+ ACE_Asynch_Write_File_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constructor. This implementation will not be deleted.
+ Result (ACE_Asynch_Write_File_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// The implementation class.
+ ACE_Asynch_Write_File_Result_Impl *implementation_;
+
+ private:
+ /// Here just to provide an dummpy implementation, since the
+ /// one auto generated by MSVC is flagged as infinitely recursive
+ void operator= (Result &) {};
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Accept_Result_Impl;
+class ACE_Asynch_Accept_Impl;
+
+/**
+ * @class ACE_Asynch_Accept
+ *
+ * @brief This class is a factory for starting off asynchronous accepts
+ * on a listen handle. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <accept>s can
+ * started using this class. A ACE_Asynch_Accept::Result will
+ * be passed back to the <handler> when the asynchronous accept
+ * completes through the <ACE_Handler::handle_accept>
+ * callback.
+ */
+class ACE_Export ACE_Asynch_Accept : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Accept (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Accept (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous accept. The asynchronous accept
+ * call also allows any initial data to be returned to the
+ * <handler>. Upto <bytes_to_read> will be read and stored in the
+ * <message_block>. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this is a no-op.
+ *
+ * <message_block> must be specified. This is because the address of
+ * the new connection is placed at the end of this buffer.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle = ACE_INVALID_HANDLE,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Accept_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Accept_Impl *implementation);
+
+ /// Delegation/implementation class that all methods will be
+ /// forwarded to.
+ ACE_Asynch_Accept_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous accept completes.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous accept.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Accept_Result;
+ friend class ACE_WIN32_Asynch_Accept_Result;
+
+ public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous accept.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for accepting new connections.
+ ACE_HANDLE listen_handle (void) const;
+
+ /// I/O handle for the new connection.
+ ACE_HANDLE accept_handle (void) const;
+
+ /// Get the implementation.
+ ACE_Asynch_Accept_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Contructor. Implementation will not be deleted.
+ Result (ACE_Asynch_Accept_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// Impelmentation class.
+ ACE_Asynch_Accept_Result_Impl *implementation_;
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Transmit_File_Result_Impl;
+class ACE_Asynch_Transmit_File_Impl;
+
+/**
+ * @class ACE_Asynch_Transmit_File
+ *
+ * @brief This class is a factory for starting off asynchronous
+ * transmit files on a stream.
+ *
+ * Once <open> is called, multiple asynchronous <transmit_file>s
+ * can started using this class. A
+ * ACE_Asynch_Transmit_File::Result will be passed back to the
+ * <handler> when the asynchronous transmit file completes
+ * through the <ACE_Handler::handle_transmit_file> callback.
+ * The transmit_file function transmits file data over a
+ * connected network connection. The function uses the operating
+ * system's cache manager to retrieve the file data. This
+ * function provides high-performance file data transfer over
+ * network connections. This function would be of great use in
+ * a Web Server, Image Server, etc.
+ */
+class ACE_Export ACE_Asynch_Transmit_File : public ACE_Asynch_Operation
+{
+
+public:
+ // Forward declarations
+ class Header_And_Trailer;
+
+ /// A do nothing constructor.
+ ACE_Asynch_Transmit_File (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Transmit_File (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous transmit file. The <file> is a
+ * handle to an open file. <header_and_trailer> is a pointer to a
+ * data structure that contains pointers to data to send before and
+ * after the file data is sent. Set this parameter to 0 if you only
+ * want to transmit the file data. Upto <bytes_to_write> will be
+ * written to the <socket>. If you want to send the entire file,
+ * let <bytes_to_write> = 0. <bytes_per_send> is the size of each
+ * block of data sent per send operation. Please read the Win32
+ * documentation on what the flags should be. Priority of the
+ * operation is specified by <priority>. On POSIX4-Unix, this is
+ * supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ int transmit_file (ACE_HANDLE file,
+ Header_And_Trailer *header_and_trailer = 0,
+ u_long bytes_to_write = 0,
+ u_long offset = 0,
+ u_long offset_high = 0,
+ u_long bytes_per_send = 0,
+ u_long flags = 0,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Transmit_File_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation.
+ void implementation (ACE_Asynch_Transmit_File_Impl *);
+
+ /// The implementation class.
+ ACE_Asynch_Transmit_File_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous transmit file completes.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous transmit file.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Transmit_File_Result;
+ friend class ACE_WIN32_Asynch_Transmit_File_Result;
+
+ public:
+ /// Socket used for transmitting the file.
+ ACE_HANDLE socket (void) const;
+
+ /// File from which the data is read.
+ ACE_HANDLE file (void) const;
+
+ /// Header and trailer data associated with this transmit file.
+ Header_And_Trailer *header_and_trailer (void) const;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous transmit file.
+ u_long bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ u_long bytes_per_send (void) const;
+
+ /// Flags which were passed into transmit file.
+ u_long flags (void) const;
+
+ /// Get the implementation class.
+ ACE_Asynch_Transmit_File_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constructor.
+ Result (ACE_Asynch_Transmit_File_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// The implementation class.
+ ACE_Asynch_Transmit_File_Result_Impl *implementation_;
+ };
+
+/**
+ * @class Header_And_Trailer
+ *
+ * @brief The class defines a data structure that contains pointers
+ * to data to send before and after the file data is sent.
+ *
+ * This class provides a wrapper over TRANSMIT_FILE_BUFFERS
+ * and provided a consistent use of ACE_Message_Blocks.
+ */
+ class ACE_Export Header_And_Trailer
+ {
+
+ public:
+ /// Constructor.
+ Header_And_Trailer (ACE_Message_Block *header = 0,
+ u_long header_bytes = 0,
+ ACE_Message_Block *trailer = 0,
+ u_long trailer_bytes = 0);
+
+ /// Destructor
+ virtual ~Header_And_Trailer (void);
+
+ /// This method allows all the member to be set in one fell swoop.
+ void header_and_trailer (ACE_Message_Block *header = 0,
+ u_long header_bytes = 0,
+ ACE_Message_Block *trailer = 0,
+ u_long trailer_bytes = 0);
+
+ /// Header which goes before the file data.
+ ACE_Message_Block *header (void) const;
+ void header (ACE_Message_Block *message_block);
+
+ /// Size of the header data.
+ u_long header_bytes (void) const;
+ void header_bytes (u_long bytes);
+
+ /// Trailer which goes after the file data.
+ ACE_Message_Block *trailer (void) const;
+ void trailer (ACE_Message_Block *message_block);
+
+ /// Size of the trailer data.
+ u_long trailer_bytes (void) const;
+ void trailer_bytes (u_long bytes);
+
+ /// Conversion routine.
+ ACE_LPTRANSMIT_FILE_BUFFERS transmit_buffers (void);
+
+ protected:
+ /// Header data.
+ ACE_Message_Block *header_;
+
+ /// Size of header data.
+ u_long header_bytes_;
+
+ /// Trailer data.
+ ACE_Message_Block *trailer_;
+
+ /// Size of trailer data.
+ u_long trailer_bytes_;
+
+ /// Target data structure.
+ ACE_TRANSMIT_FILE_BUFFERS transmit_buffers_;
+ };
+};
+
+
+// Forward declarations
+class ACE_Asynch_Read_Dgram_Result_Impl;
+class ACE_Asynch_Read_Dgram_Impl;
+class ACE_Addr;
+
+/**
+ * @class ACE_Asynch_Read_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a UDP socket. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can be
+ * started using this class. An ACE_Asynch_Read_Dgram::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_dgram>
+ * callback.
+ */
+class ACE_Export ACE_Asynch_Read_Dgram : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Read_Dgram (void);
+
+ /// Destructor
+ virtual ~ACE_Asynch_Read_Dgram (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /** This starts off an asynchronous read. Upto
+ * <message_block->total_size()> will be read and stored in the
+ * <message_block>. <message_block>'s <wr_ptr> will be updated to reflect
+ * the added bytes if the read operation is successfully completed.
+ * Return code of 1 means immediate success and <number_of_bytes_recvd>
+ * will contain number of bytes read. The <ACE_Handler::handle_read_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->size()> bytes will be read into each <message block> for
+ * a total of <message_block->total_size()> bytes. All <message_block>'s
+ * <wr_ptr>'s will be updated to reflect the added bytes for each
+ * <message_block>
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, <priority> is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ ssize_t recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family = PF_INET,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Read_Dgram_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Read_Dgram_Impl *implementation);
+
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Read_Dgram_Impl *implementation_;
+
+public:
+/**
+ * @class Result
+ *
+ * @brief This is the class which will be passed back to the
+ * <handler> when the asynchronous read completes. This class
+ * forwards all the methods to the implementation classes.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous read.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Read_Dgram_Result;
+ friend class ACE_WIN32_Asynch_Read_Dgram_Result;
+
+ public:
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The flags used in the read
+ int flags (void) const;
+
+ /// The address of where the packet came from
+ int remote_address (ACE_Addr& addr) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ /// Get the implementation class.
+ ACE_Asynch_Read_Dgram_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constructor.
+ Result (ACE_Asynch_Read_Dgram_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// The implementation class.
+ ACE_Asynch_Read_Dgram_Result_Impl *implementation_;
+ };
+};
+
+// Forward declarations
+class ACE_Asynch_Write_Dgram_Impl;
+class ACE_Asynch_Write_Dgram_Result_Impl;
+
+/**
+ * @class ACE_Asynch_Write_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a UDP socket. This class forwards all methods to its
+ * implementation class.
+ *
+ * Once <open> is called, multiple asynchronous <writes>s can
+ * started using this class. An ACE_Asynch_Write_Dgram::Result
+ * will be passed back to the <handler> when the asynchronous
+ * write completes through the
+ * <ACE_Handler::handle_write_dgram> callback.
+ */
+class ACE_Export ACE_Asynch_Write_Dgram : public ACE_Asynch_Operation
+{
+
+public:
+ /// A do nothing constructor.
+ ACE_Asynch_Write_Dgram (void);
+
+ /// Destructor.
+ virtual ~ACE_Asynch_Write_Dgram (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ const void *completion_key = 0,
+ ACE_Proactor *proactor = 0);
+
+ /** This starts off an asynchronous send. Upto
+ * <message_block->total_length()> will be sent. <message_block>'s
+ * <rd_ptr> will be updated to reflect the sent bytes if the send operation
+ * is successfully completed.
+ * Return code of 1 means immediate success and <number_of_bytes_sent>
+ * is updated to number of bytes sent. The <ACE_Handler::handle_write_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->length()> bytes will be sent from each <message block>
+ * for a total of <message_block->total_length()> bytes. All
+ * <message_block>'s <rd_ptr>'s will be updated to reflect the bytes sent
+ * from each <message_block>.
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this argument is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ ssize_t send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr& remote_addr,
+ const void *act = 0,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Return the underlying implementation class.
+ ACE_Asynch_Write_Dgram_Impl *implementation (void) const;
+
+protected:
+ /// Set the implementation class.
+ void implementation (ACE_Asynch_Write_Dgram_Impl *implementation);
+
+ /// Implementation class that all methods will be forwarded to.
+ ACE_Asynch_Write_Dgram_Impl *implementation_;
+
+public:
+/**
+ * @class
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous write completes. This class
+ * forwards all the methods to the implementation class.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ */
+ class ACE_Export Result : public ACE_Asynch_Result
+ {
+
+ /// The concrete implementation result classes only construct this
+ /// class.
+ friend class ACE_POSIX_Asynch_Write_Dgram_Result;
+ friend class ACE_WIN32_Asynch_Write_Dgram_Result;
+
+ public:
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block which contains the sent data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The flags using in the write
+ int flags (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ /// Get the implementation class.
+ ACE_Asynch_Write_Dgram_Result_Impl *implementation (void) const;
+
+ protected:
+ /// Constrcutor.
+ Result (ACE_Asynch_Write_Dgram_Result_Impl *implementation);
+
+ /// Destructor.
+ virtual ~Result (void);
+
+ /// Implementation class.
+ ACE_Asynch_Write_Dgram_Result_Impl *implementation_;
+ };
+};
+
+
+/**
+ * @class ACE_Handler
+ *
+ * @brief This base class defines the interface for receiving the
+ * results of asynchronous operations.
+ *
+ * Subclasses of this class will fill in appropriate methods.
+ */
+class ACE_Export ACE_Handler
+{
+public:
+ /// A do nothing constructor.
+ ACE_Handler (void);
+
+ /// A do nothing constructor which allows proactor to be set to <p>.
+ ACE_Handler (ACE_Proactor *p);
+
+ /// Virtual destruction.
+ virtual ~ACE_Handler (void);
+
+ /// This method will be called when an asynchronous read completes on
+ /// a stream.
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+
+ /// This method will be called when an asynchronous write completes
+ /// on a UDP socket.
+ virtual void handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result);
+
+ /// This method will be called when an asynchronous read completes on
+ /// a UDP socket.
+ virtual void handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result);
+
+ /// This method will be called when an asynchronous write completes
+ /// on a stream.
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+
+ /// This method will be called when an asynchronous read completes on
+ /// a file.
+ virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
+
+ /// This method will be called when an asynchronous write completes
+ /// on a file.
+ virtual void handle_write_file (const ACE_Asynch_Write_File::Result &result);
+
+ /// This method will be called when an asynchronous accept completes.
+ virtual void handle_accept (const ACE_Asynch_Accept::Result &result);
+
+ /// This method will be called when an asynchronous transmit file
+ /// completes.
+ virtual void handle_transmit_file (const ACE_Asynch_Transmit_File::Result &result);
+
+ /// Called when timer expires. <tv> was the requested time value and
+ /// <act> is the ACT passed when scheduling the timer.
+ virtual void handle_time_out (const ACE_Time_Value &tv,
+ const void *act = 0);
+
+ /**
+ * This is method works with the <run_event_loop> of the
+ * ACE_Proactor. A special <Wake_Up_Completion> is used to wake up
+ * all the threads that are blocking for completions.
+ */
+ virtual void handle_wakeup (void);
+
+ /// Get the proactor associated with this handler.
+ ACE_Proactor *proactor (void);
+
+ /// Set the proactor.
+ void proactor (ACE_Proactor *p);
+
+ /**
+ * Get the I/O handle used by this <handler>. This method will be
+ * called by the ACE_Asynch_* classes when an ACE_INVALID_HANDLE is
+ * passed to <open>.
+ */
+ virtual ACE_HANDLE handle (void) const;
+
+ /// Set the ACE_HANDLE value for this Handler.
+ virtual void handle (ACE_HANDLE);
+
+protected:
+ /// The proactor associated with this handler.
+ ACE_Proactor *proactor_;
+
+ /// The ACE_HANDLE in use with this handler.
+ ACE_HANDLE handle_;
+};
+
+// Forward declarations
+class ACE_INET_Addr;
+
+// Forward declarations
+template <class HANDLER>
+class ACE_Asynch_Acceptor;
+
+/**
+ * @class ACE_Service_Handler
+ *
+ * @brief This base class defines the interface for the
+ * ACE_Asynch_Acceptor to call into when new connection are
+ * accepted.
+ *
+ * Subclasses of this class will fill in appropriate methods to
+ * define application specific behavior.
+ */
+class ACE_Export ACE_Service_Handler : public ACE_Handler
+{
+
+ /// The Acceptor is the factory and therefore should have special
+ /// privileges.
+ friend class ACE_Asynch_Acceptor<ACE_Service_Handler>;
+
+public:
+ /// A do nothing constructor.
+ ACE_Service_Handler (void);
+
+ /// Virtual destruction.
+ virtual ~ACE_Service_Handler (void);
+
+ /**
+ * <open> is called by ACE_Asynch_Acceptor to initialize a new
+ * instance of ACE_Service_Handler that has been created after the a
+ * new connection is accepted. The handle for the new connection is
+ * passed along with an initial data that may have shown up.
+ */
+ virtual void open (ACE_HANDLE new_handle,
+ ACE_Message_Block &message_block);
+
+ // protected:
+ // This should be corrected after the correct semantics of the
+ // friend has been figured out.
+
+ /// Called by ACE_Asynch_Acceptor to pass the addresses of the new
+ /// connections.
+ virtual void addresses (const ACE_INET_Addr &remote_address,
+ const ACE_INET_Addr &local_address);
+
+ /// Called by ACE_Asynch_Acceptor to pass the act.
+ virtual void act (const void *);
+};
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS*/
+#include "ace/post.h"
+#endif /* ACE_ASYNCH_IO_H */
diff --git a/ace/Connection/Asynch_IO_Impl.cpp b/ace/Connection/Asynch_IO_Impl.cpp
new file mode 100644
index 00000000000..ac079a80994
--- /dev/null
+++ b/ace/Connection/Asynch_IO_Impl.cpp
@@ -0,0 +1,108 @@
+// $Id$
+#include "ace/OS.h"
+#include "ace/Asynch_IO_Impl.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+// This only works on Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Asynch_IO_Impl.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_Asynch_Result_Impl::~ACE_Asynch_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Operation_Impl::~ACE_Asynch_Operation_Impl (void)
+{
+}
+
+ACE_Asynch_Read_Stream_Impl::~ACE_Asynch_Read_Stream_Impl (void)
+{
+}
+
+ACE_Asynch_Read_Stream_Result_Impl::~ACE_Asynch_Read_Stream_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Write_Stream_Impl::~ACE_Asynch_Write_Stream_Impl (void)
+{
+}
+
+ACE_Asynch_Write_Stream_Result_Impl::~ACE_Asynch_Write_Stream_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Read_File_Impl::~ACE_Asynch_Read_File_Impl (void)
+{
+}
+
+ACE_Asynch_Write_File_Impl::~ACE_Asynch_Write_File_Impl (void)
+{
+}
+
+ACE_Asynch_Read_File_Result_Impl::~ACE_Asynch_Read_File_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Write_File_Result_Impl::~ACE_Asynch_Write_File_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Accept_Result_Impl::~ACE_Asynch_Accept_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Accept_Impl::~ACE_Asynch_Accept_Impl (void)
+{
+}
+
+ACE_Asynch_Transmit_File_Impl::~ACE_Asynch_Transmit_File_Impl (void)
+{
+}
+
+ACE_Asynch_Transmit_File_Result_Impl::~ACE_Asynch_Transmit_File_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Read_Dgram_Impl::~ACE_Asynch_Read_Dgram_Impl (void)
+{
+}
+
+ACE_Asynch_Read_Dgram_Impl::ACE_Asynch_Read_Dgram_Impl (void)
+{
+}
+
+ACE_Asynch_Write_Dgram_Impl::~ACE_Asynch_Write_Dgram_Impl (void)
+{
+}
+
+ACE_Asynch_Write_Dgram_Impl::ACE_Asynch_Write_Dgram_Impl (void)
+{
+}
+
+//***********************************************
+
+ACE_Asynch_Read_Dgram_Result_Impl::~ACE_Asynch_Read_Dgram_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl::ACE_Asynch_Read_Dgram_Result_Impl (void)
+{
+}
+
+//***********************************************
+
+ACE_Asynch_Write_Dgram_Result_Impl::~ACE_Asynch_Write_Dgram_Result_Impl (void)
+{
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl::ACE_Asynch_Write_Dgram_Result_Impl (void)
+{
+}
+
+
+
+
+#endif /* ACE_WIN32 || ACE_HAS_WINCE */
diff --git a/ace/Connection/Asynch_IO_Impl.h b/ace/Connection/Asynch_IO_Impl.h
new file mode 100644
index 00000000000..5137145534d
--- /dev/null
+++ b/ace/Connection/Asynch_IO_Impl.h
@@ -0,0 +1,684 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Asynch_IO_Impl.h
+ *
+ * $Id$
+ *
+ *
+ * This class contains asbtract base classes for all the concrete
+ * implementation classes for the various asynchronous operations
+ * that are used with the Praoctor.
+ *
+ *
+ * @author Irfan Pyarali (irfan@cs.wustl.edu)
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ */
+//=============================================================================
+
+#ifndef ACE_ASYNCH_IO_IMPL_H
+#define ACE_ASYNCH_IO_IMPL_H
+#include "ace/pre.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+// This only works on Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+#include "ace/Asynch_IO.h"
+
+// Forward declaration.
+class ACE_Proactor_Impl;
+
+/**
+ * @class ACE_Asynch_Result_Impl
+ *
+ * @brief Abstract base class for the all the classes that provide
+ * concrete implementations for ACE_Asynch_Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Result_Impl (void);
+
+ /// Number of bytes transferred by the operation.
+ virtual u_long bytes_transferred (void) const = 0;
+
+ /// ACT associated with the operation.
+ virtual const void *act (void) const = 0;
+
+ /// Did the operation succeed?
+ virtual int success (void) const = 0;
+
+ /// This ACT is not the same as the ACT associated with the
+ /// asynchronous operation.
+ virtual const void *completion_key (void) const = 0;
+
+ /// Error value if the operation fail.
+ virtual u_long error (void) const = 0;
+
+ /// Event associated with the OVERLAPPED structure.
+ virtual ACE_HANDLE event (void) const = 0;
+
+ /// This really make sense only when doing file I/O.
+ virtual u_long offset (void) const = 0;
+ virtual u_long offset_high (void) const = 0;
+
+ /// Priority of the operation.
+ virtual int priority (void) const = 0;
+
+ /**
+ * POSIX4 real-time signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ virtual int signal_number (void) const = 0;
+
+ // protected:
+ //
+ // These two should really be protected. But sometimes it
+ // simplifies code to be able to "fake" a result. Use carefully.
+ /// This is called when the asynchronous operation completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0) = 0;
+
+ /// Post <this> to the Proactor's completion port.
+ virtual int post_completion (ACE_Proactor_Impl *proactor) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Operation_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Operation.
+ */
+class ACE_Export ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Operation_Impl (void);
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ virtual int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor) = 0;
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ virtual int cancel (void) = 0;
+
+ // = Access methods.
+
+ /// Return the underlying proactor.
+ virtual ACE_Proactor* proactor (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Operation_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Read_Stream_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Read_Stream
+ *
+ */
+class ACE_Export ACE_Asynch_Read_Stream_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Read_Stream_Impl (void);
+
+ /// This starts off an asynchronous read. Upto <bytes_to_read> will
+ /// be read and stored in the <message_block>.
+ virtual int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_Stream_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Read_Stream_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Read_Stream::Result class.
+ *
+ */
+class ACE_Export ACE_Asynch_Read_Stream_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Read_Stream_Result_Impl (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ virtual u_long bytes_to_read (void) const = 0;
+
+ /// Message block which contains the read data.
+ virtual ACE_Message_Block &message_block (void) const = 0;
+
+ /// I/O handle used for reading.
+ virtual ACE_HANDLE handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_Stream_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_Stream_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Write_Stream class.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_Stream_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_Stream_Impl (void);
+
+ /// This starts off an asynchronous write. Upto <bytes_to_write>
+ /// will be written from the <message_block>.
+ virtual int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_Stream_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_Stream_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Write_Stream::Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_Stream_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_Stream_Result_Impl (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ virtual u_long bytes_to_write (void) const = 0;
+
+ /// Message block that contains the data to be written.
+ virtual ACE_Message_Block &message_block (void) const = 0;
+
+ /// I/O handle used for writing.
+ virtual ACE_HANDLE handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_Stream_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Read_File_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Read_File::Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Read_File_Impl : public virtual ACE_Asynch_Read_Stream_Impl
+{
+public:
+ virtual ~ACE_Asynch_Read_File_Impl (void);
+
+ /**
+ * This starts off an asynchronous read. Upto <bytes_to_read> will
+ * be read and stored in the <message_block>. The read will start
+ * at <offset> from the beginning of the file.
+ */
+ virtual int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+ // We don;t need to redefine the following function again because it
+ // has already been defined in ACE_Asynch_Read_Stream_Impl. But we
+ // still need it here to supress a overwriting pure virtual function
+ // warning in KAI compiler.
+ /// This starts off an asynchronous read. Upto <bytes_to_read> will
+ /// be read and stored in the <message_block>.
+ virtual int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_File_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Read_File_Result_Impl
+ *
+ * @brief This is the abstract base class for all the concrete
+ * implementation classes for ACE_Asynch_Read_File::Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Read_File_Result_Impl : public virtual ACE_Asynch_Read_Stream_Result_Impl
+{
+public:
+ /// Destructor.
+ virtual ~ACE_Asynch_Read_File_Result_Impl (void);
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_File_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_File_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Write_File.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_File_Impl : public virtual ACE_Asynch_Write_Stream_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_File_Impl (void);
+
+ /**
+ * This starts off an asynchronous write. Upto <bytes_to_write>
+ * will be write and stored in the <message_block>. The write will
+ * start at <offset> from the beginning of the file.
+ */
+ virtual int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+ // We don;t need to redefine the following function again because it
+ // has already been defined in ACE_Asynch_Write_Stream_Impl. But we
+ // still need it here to supress a overwriting pure virtual function
+ // warning in KAI compiler.
+ /// This starts off an asynchronous write. Upto <bytes_to_write>
+ /// will be written from the <message_block>.
+ virtual int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_File_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_File_Result_Impl
+ *
+ * @brief This is the abstract base class for all the concrete
+ * implementation classes that provide different implementations
+ * for the ACE_Asynch_Write_File::Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_File_Result_Impl : public virtual ACE_Asynch_Write_Stream_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_File_Result_Impl (void);
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_File_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Accept_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Accept.
+ *
+ */
+class ACE_Export ACE_Asynch_Accept_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Accept_Impl (void);
+
+ /**
+ * This starts off an asynchronous accept. The asynchronous accept
+ * call also allows any initial data to be returned to the
+ * <handler>. Upto <bytes_to_read> will be read and stored in the
+ * <message_block>. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * <message_block> must be specified. This is because the address of
+ * the new connection is placed at the end of this buffer.
+ */
+ virtual int accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Accept_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Accept_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Accept.
+ *
+ */
+class ACE_Export ACE_Asynch_Accept_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Accept_Result_Impl (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous accept.
+ virtual u_long bytes_to_read (void) const = 0;
+
+ /// Message block which contains the read data.
+ virtual ACE_Message_Block &message_block (void) const = 0;
+
+ /// I/O handle used for accepting new connections.
+ virtual ACE_HANDLE listen_handle (void) const = 0;
+
+ /// I/O handle for the new connection.
+ virtual ACE_HANDLE accept_handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Accept_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Transmit_File_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Transmit_File.
+ *
+ */
+class ACE_Asynch_Transmit_File_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Transmit_File_Impl (void);
+
+ /// This starts off an asynchronous transmit file.
+ virtual int transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Transmit_File_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Transmit_File_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Transmit_File::Result.
+ *
+ */
+class ACE_Export ACE_Asynch_Transmit_File_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Transmit_File_Result_Impl (void);
+
+ /// Socket used for transmitting the file.
+ virtual ACE_HANDLE socket (void) const = 0;
+
+ /// File from which the data is read.
+ virtual ACE_HANDLE file (void) const = 0;
+
+ /// Header and trailer data associated with this transmit file.
+ virtual ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer (void) const = 0;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous transmit file.
+ virtual u_long bytes_to_write (void) const = 0;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ virtual u_long bytes_per_send (void) const = 0;
+
+ /// Flags which were passed into transmit file.
+ virtual u_long flags (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Transmit_File_Result_Impl (void);
+};
+
+
+/**
+ * @class ACE_Asynch_Read_Dgram_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Read_Dgram
+ *
+ */
+class ACE_Export ACE_Asynch_Read_Dgram_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Read_Dgram_Impl (void);
+
+ /** This starts off an asynchronous read. Upto
+ * <message_block->total_size()> will be read and stored in the
+ * <message_block>. <message_block>'s <wr_ptr> will be updated to reflect
+ * the added bytes if the read operation is successful completed.
+ * Return code of 1 means immediate success and <number_of_bytes_recvd>
+ * will contain number of bytes read. The <ACE_Handler::handle_read_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->size()> bytes will be read into each <message block> for
+ * a total of <message_block->total_size()> bytes. All <message_block>'s
+ * <wr_ptr>'s will be updated to reflect the added bytes for each
+ * <message_block>
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, <priority> is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ virtual ssize_t recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_Dgram_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Read_Dgram_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Read_Dgram::Result class.
+ *
+ */
+class ACE_Export ACE_Asynch_Read_Dgram_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Read_Dgram_Result_Impl (void);
+
+ /// Message block which contains the read data
+ virtual ACE_Message_Block *message_block (void) const = 0;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ virtual u_long bytes_to_read (void) const = 0;
+
+ /// The address of where the packet came from
+ virtual int remote_address (ACE_Addr& addr) const = 0;
+
+ /// The flags used in the read
+ virtual int flags (void) const = 0;
+
+ /// I/O handle used for reading.
+ virtual ACE_HANDLE handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Read_Dgram_Result_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_Dgram_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Write_Dgram class.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_Dgram_Impl : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_Dgram_Impl (void);
+
+ /** This starts off an asynchronous send. Upto
+ * <message_block->total_length()> will be sent. <message_block>'s
+ * <rd_ptr> will be updated to reflect the sent bytes if the send operation
+ * is successful completed.
+ * Return code of 1 means immediate success and <number_of_bytes_sent>
+ * is updated to number of bytes sent. The <ACE_Handler::handle_write_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->length()> bytes will be sent from each <message block>
+ * for a total of <message_block->total_length()> bytes. All
+ * <message_block>'s <rd_ptr>'s will be updated to reflect the bytes sent
+ * from each <message_block>.
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. On Win32, this argument is a no-op.
+ * <signal_number> is the POSIX4 real-time signal number to be used
+ * for the operation. <signal_number> ranges from ACE_SIGRTMIN to
+ * ACE_SIGRTMAX. This argument is a no-op on non-POSIX4 systems.
+ */
+ virtual ssize_t send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ const void *act,
+ int priority,
+ int signal_number) = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_Dgram_Impl (void);
+};
+
+/**
+ * @class ACE_Asynch_Write_Dgram_Result_Impl
+ *
+ * @brief Abstract base class for all the concrete implementation
+ * classes that provide different implementations for the
+ * ACE_Asynch_Write_Dgram::Result class.
+ *
+ */
+class ACE_Export ACE_Asynch_Write_Dgram_Result_Impl : public virtual ACE_Asynch_Result_Impl
+{
+public:
+ virtual ~ACE_Asynch_Write_Dgram_Result_Impl (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ virtual u_long bytes_to_write (void) const = 0;
+
+ /// Message block which contains the sent data
+ virtual ACE_Message_Block *message_block (void) const = 0;
+
+ /// The flags using in the write
+ virtual int flags (void) const = 0;
+
+ /// I/O handle used for writing.
+ virtual ACE_HANDLE handle (void) const = 0;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_Asynch_Write_Dgram_Result_Impl (void);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Asynch_IO_Impl.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_AIO_CALLS || !ACE_HAS_WINCE && ACE_WIN32 */
+#include "ace/post.h"
+#endif /* ACE_ASYNCH_IO_IMPL_H */
diff --git a/ace/Connection/Asynch_IO_Impl.i b/ace/Connection/Asynch_IO_Impl.i
new file mode 100644
index 00000000000..a6c36925943
--- /dev/null
+++ b/ace/Connection/Asynch_IO_Impl.i
@@ -0,0 +1,87 @@
+// $Id$
+
+ACE_INLINE
+ACE_Asynch_Result_Impl::ACE_Asynch_Result_Impl (void)
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Operation_Impl::ACE_Asynch_Operation_Impl (void)
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Read_Stream_Impl::ACE_Asynch_Read_Stream_Impl (void)
+ : ACE_Asynch_Operation_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Read_Stream_Result_Impl::ACE_Asynch_Read_Stream_Result_Impl (void)
+ : ACE_Asynch_Result_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Write_Stream_Impl::ACE_Asynch_Write_Stream_Impl (void)
+ : ACE_Asynch_Operation_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Write_Stream_Result_Impl::ACE_Asynch_Write_Stream_Result_Impl (void)
+ : ACE_Asynch_Result_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Read_File_Impl::ACE_Asynch_Read_File_Impl (void)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Stream_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Read_File_Result_Impl::ACE_Asynch_Read_File_Result_Impl (void)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Write_File_Impl::ACE_Asynch_Write_File_Impl (void)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Stream_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Write_File_Result_Impl::ACE_Asynch_Write_File_Result_Impl (void)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Accept_Impl::ACE_Asynch_Accept_Impl (void)
+ : ACE_Asynch_Operation_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Accept_Result_Impl::ACE_Asynch_Accept_Result_Impl (void)
+ : ACE_Asynch_Result_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Transmit_File_Impl::ACE_Asynch_Transmit_File_Impl (void)
+ : ACE_Asynch_Operation_Impl ()
+{
+}
+
+ACE_INLINE
+ACE_Asynch_Transmit_File_Result_Impl::ACE_Asynch_Transmit_File_Result_Impl (void)
+ : ACE_Asynch_Result_Impl ()
+{
+}
diff --git a/ace/Connection/Caching_Strategies_T.cpp b/ace/Connection/Caching_Strategies_T.cpp
new file mode 100644
index 00000000000..0d4f389c966
--- /dev/null
+++ b/ace/Connection/Caching_Strategies_T.cpp
@@ -0,0 +1,57 @@
+//$Id$
+
+#ifndef CACHING_STRATEGIES_T_C
+#define CACHING_STRATEGIES_T_C
+
+#include "ace/Caching_Strategies_T.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Caching_Strategies_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#define ACE_LACKS_PRAGMA_ONCE
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Caching_Strategies_T, "$Id$")
+
+template<class ATTRIBUTES, class CACHING_UTILITY>
+ACE_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::~ACE_Caching_Strategy (void)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY>
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::ACE_LRU_Caching_Strategy (void)
+ : timer_ (0),
+ purge_percent_ (10)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY>
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::ACE_LFU_Caching_Strategy (void)
+ : purge_percent_ (10)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY>
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::ACE_FIFO_Caching_Strategy (void)
+ : order_ (0),
+ purge_percent_ (10)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LRU_Caching_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_LFU_Caching_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Caching_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Null_Caching_Strategy)
+
+#endif /* CACHING_STRATEGIES_T_C */
diff --git a/ace/Connection/Caching_Strategies_T.h b/ace/Connection/Caching_Strategies_T.h
new file mode 100644
index 00000000000..3c6dbef3a8e
--- /dev/null
+++ b/ace/Connection/Caching_Strategies_T.h
@@ -0,0 +1,537 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Caching_Strategies_T.h
+ *
+ * $Id$
+ *
+ * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef CACHING_STRATEGIES_H
+#define CACHING_STRATEGIES_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+#include "ace/Caching_Utility_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#define ACE_LACKS_PRAGMA_ONCE
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4503)
+#endif /* _MSC_VER */
+
+// For linkers that cant grok long names.
+#define ACE_Caching_Strategy ACS
+
+/**
+ * @class ACE_Caching_Strategy
+ *
+ * @brief This class is an abstract base class for a caching strategy.
+ *
+ * This class consists of all the interfaces a caching strategy should have and
+ * is used in association with the ACE_Caching_Strategy_Adaptor.
+ */
+template <class ATTRIBUTES, class CACHING_UTILITY>
+class ACE_Caching_Strategy
+{
+public:
+ /// Destructor.
+ virtual ~ACE_Caching_Strategy (void);
+
+ /// Accessor method for the timer attributes.
+ virtual ATTRIBUTES attributes (void) = 0;
+
+ // = Accessor methods for the percentage of entries to purge.
+ virtual double purge_percent (void) = 0;
+ virtual void purge_percent (double percentage) = 0;
+
+ // = Strategy related Operations
+
+ /// This method acts as a notification about the CONTAINERs bind
+ /// method call.
+ virtual int notify_bind (int result,
+ const ATTRIBUTES &attr) = 0;
+
+ /// This method acts as a notification about the CONTAINERs find
+ /// method call
+ virtual int notify_find (int result,
+ ATTRIBUTES &attr) = 0;
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ virtual int notify_unbind (int result,
+ const ATTRIBUTES &attr) = 0;
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ virtual int notify_trybind (int result,
+ ATTRIBUTES &attr) = 0;
+
+ /// This method acts as a notification about the CONTAINERs rebind
+ /// method call
+ virtual int notify_rebind (int result,
+ const ATTRIBUTES &attr) = 0;
+
+ /// Purge the cache.
+ virtual CACHING_UTILITY &caching_utility (void) = 0;
+
+ /// Dumps the state of the object.
+ virtual void dump (void) const = 0;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+#define ACE_Caching_Strategy_Adapter ACSA
+
+/**
+ * @class ACE_Caching_Strategy_Adapter
+ *
+ * @brief This class follows the Adaptor pattern and is used to provide
+ * External Polymorphism by deriving from ACE_Caching_Strategy.
+ *
+ * This class simply delegates all requests to the
+ * IMPLEMNETATION object within. This class should be passed in
+ * place of the the abstract base ACE_Caching_Strategy class as
+ * part of the External Polymorphism pattern.
+ */
+template <class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION>
+class ACE_Caching_Strategy_Adapter : public ACE_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>
+{
+
+public:
+
+ /// Constructor.
+ ACE_Caching_Strategy_Adapter (IMPLEMENTATION *implementation = 0,
+ int delete_implementation = 0);
+
+ /// Destructor.
+ ~ACE_Caching_Strategy_Adapter (void);
+
+ /// Accessor method for the timer attributes.
+ ATTRIBUTES attributes (void);
+
+ // = Accessor methods for the percentage of entries to purge.
+ double purge_percent (void);
+ void purge_percent (double percentage);
+
+ // = Strategy related Operations
+
+ /// This method acts as a notification about the CONTAINERs bind
+ /// method call.
+ int notify_bind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs find
+ /// method call
+ int notify_find (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ int notify_unbind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ int notify_trybind (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs rebind
+ /// method call
+ int notify_rebind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Accessor to the implementation.
+ IMPLEMENTATION &implementation (void);
+
+ /// Purge the cache.
+ CACHING_UTILITY &caching_utility (void);
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+private:
+
+ /// Implementation class.
+ IMPLEMENTATION *implementation_;
+
+ /// Do we need to delete the implementation?
+ int delete_implementation_;
+};
+
+//////////////////////////////////////////////////////////////////////////
+#define ACE_LRU_Caching_Strategy ALRU
+
+/**
+ * @class ACE_LRU_Caching_Strategy
+ *
+ * @brief Defines a Least Recently Used strategy which will decide on
+ * the item to be removed from the cache.
+ *
+ * This is a strategy which makes use of a virtual timer which
+ * is updated whenever an item is inserted or looked up in the
+ * container. When the need of purging entries arises, the items
+ * with the lowest timer values are removed.
+ * Explanation of the template parameter list:
+ * CONTAINER is any map with entries of type <KEY, VALUE>.
+ * The ATTRIBUTES are the deciding factor for purging of entries
+ * and should logically be included with the VALUE. Some ways of
+ * doing this are: As being a member of the VALUE or VALUE being
+ * ACE_Pair<x, ATTRIBUTES>. The CACHING_UTILITY is the
+ * class which can be plugged in and which decides the entries
+ * to purge.
+ */
+template <class ATTRIBUTES, class CACHING_UTILITY>
+class ACE_LRU_Caching_Strategy
+{
+
+public:
+
+ // Traits.
+ typedef ATTRIBUTES CACHING_ATTRIBUTES;
+
+ // = Initialisation and termination.
+
+ /**
+ * The <container> is the map in which the entries reside. The
+ * timer attribute is initialed to zero in this constructor. And
+ * the <purge_percent> field denotes the percentage of the entries
+ * in the cache which can be purged automagically and by default is
+ * set to 10%.
+ */
+ ACE_LRU_Caching_Strategy (void);
+
+ // = Operations of the strategy.
+
+ /// Accessor method for the timer attributes.
+ ATTRIBUTES attributes (void);
+
+ // = Accessor methods for the percentage of entries to purge.
+ double purge_percent (void);
+
+ void purge_percent (double percentage);
+
+ // = Strategy related Operations
+
+ /// This method acts as a notification about the CONTAINERs bind
+ /// method call.
+ int notify_bind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs find
+ /// method call
+ int notify_find (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ int notify_unbind (int result,
+ const ATTRIBUTES &attr);
+
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ int notify_trybind (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs rebind
+ /// method call
+ int notify_rebind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Purge the cache.
+ CACHING_UTILITY &caching_utility (void);
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+private:
+
+ /// This element is the one which is the deciding factor for purging
+ /// of an ITEM.
+ ATTRIBUTES timer_;
+
+ /// The level about which the purging will happen automagically.
+ double purge_percent_;
+
+ /// This is the helper class which will decide and expunge entries
+ /// from the cache.
+ CACHING_UTILITY caching_utility_;
+};
+
+//////////////////////////////////////////////////////////////////////////
+#define ACE_LFU_Caching_Strategy ALFU
+
+/**
+ * @class ACE_LFU_Caching_Strategy
+ *
+ * @brief Defines a Least Frequently Used strategy for which will decide on
+ * the item to be removed from the cache.
+ *
+ * A attribute is tagged to each item which increments whenever
+ * the item is bound or looked up in the cache. Thus it denotes
+ * the frequency of use. According to the value of the attribute
+ * the item is removed from the CONTAINER i.e cache.
+ * Explanation of the template parameter list:
+ * CONTAINER is any map with entries of type <KEY, VALUE>.
+ * The ATTRIBUTES are the deciding factor for purging of entries
+ * and should logically be included with the VALUE. Some ways of
+ * doing this are: As being a member of the VALUE or VALUE being
+ * ACE_Pair<x, ATTRIBUTES>. The CACHING_UTILITY is the
+ * class which can be plugged in and which decides the entries
+ * to purge.
+ */
+template <class ATTRIBUTES, class CACHING_UTILITY>
+class ACE_LFU_Caching_Strategy
+{
+
+public:
+
+ // Traits.
+ typedef ATTRIBUTES CACHING_ATTRIBUTES;
+
+ // = Initialisation and termination methods.
+
+ /**
+ * The <container> is the map in which the entries reside. The
+ * timer attribute is initialed to zero in this constructor. And
+ * the <purge_percent> field denotes the percentage of the entries
+ * in the cache which can be purged automagically and by default is
+ * set to 10%.
+ */
+ ACE_LFU_Caching_Strategy (void);
+
+ // = Strategy methods.
+
+ /// Access the attributes.
+ ATTRIBUTES attributes (void);
+
+ // = Accessor methods for the percentage of entries to purge.
+ double purge_percent (void);
+
+ void purge_percent (double percentage);
+
+ // = Strategy related Operations
+
+ /// This method acts as a notification about the CONTAINERs bind
+ /// method call.
+ int notify_bind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Lookup notification.
+ int notify_find (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ int notify_unbind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ int notify_trybind (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs rebind
+ /// method call
+ int notify_rebind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Purge the cache.
+ CACHING_UTILITY &caching_utility (void);
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+private:
+
+ /// The level about which the purging will happen automagically.
+ double purge_percent_;
+
+ /// This is the helper class which will decide and expunge entries
+ /// from the cache.
+ CACHING_UTILITY caching_utility_;
+};
+
+/////////////////////////////////////////////////////////////
+#define ACE_FIFO_Caching_Strategy AFIFO
+
+/**
+ * @class ACE_FIFO_Caching_Strategy
+ *
+ * @brief The First In First Out strategy is implemented wherein each
+ * item is ordered.
+ *
+ * The order tag of each item is used to decide the item to be
+ * removed from the cache. The items with least order are removed.
+ * Explanation of the template parameter list:
+ * CONTAINER is any map with entries of type <KEY, VALUE>.
+ * The ATTRIBUTES are the deciding factor for purging of entries
+ * and should logically be included with the VALUE. Some ways of
+ * doing this are: As being a member of the VALUE or VALUE being
+ * ACE_Pair<x, ATTRIBUTES>. The CACHING_UTILITY is the
+ * class which can be plugged in and which decides the entries
+ * to purge.
+ */
+template<class ATTRIBUTES, class CACHING_UTILITY>
+class ACE_FIFO_Caching_Strategy
+{
+
+public:
+
+ typedef ATTRIBUTES CACHING_ATTRIBUTES;
+
+ // = Initialisation and termination.
+
+ /**
+ * The <container> is the map in which the entries reside. The
+ * timer attribute is initialed to zero in this constructor. And
+ * the <purge_percent> field denotes the percentage of the entries
+ * in the cache which can be purged automagically and by default is
+ * set to 10%.
+ */
+ ACE_FIFO_Caching_Strategy (void);
+
+ // = Strategy methods.
+
+ /// Accessor method.
+ ATTRIBUTES attributes (void);
+
+ // = Accessor methods for the percentage of entries to purge.
+ double purge_percent (void);
+
+ void purge_percent (double percentage);
+
+ // = Strategy related Operations
+
+ /// Notification for an item getting bound into the cache.
+ int notify_bind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs find
+ /// method call
+ int notify_find (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ int notify_unbind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ int notify_trybind (int result,
+ ATTRIBUTES &attr);
+
+ /// Notification for an item getting bound again into the cache.
+ int notify_rebind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Purge the cache.
+ CACHING_UTILITY &caching_utility (void);
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+private:
+
+ /// The order is the deciding factor for the item to be removed from
+ /// the cache.
+ ATTRIBUTES order_;
+
+ /// The level about which the purging will happen automagically.
+ double purge_percent_;
+
+ /// This is the helper class which will decide and expunge entries
+ /// from the cache.
+ CACHING_UTILITY caching_utility_;
+};
+
+//////////////////////////////////////////////////////////////////////
+#define ACE_Null_Caching_Strategy ANULL
+
+/**
+ * @class ACE_Null_Caching_Strategy
+ *
+ * @brief The is a special caching strategy which doesnt have the purging
+ * feature.
+ *
+ * No purging provided. To be used when purging might be too expensive
+ * an operation.
+ */
+template<class ATTRIBUTES, class CACHING_UTILITY>
+class ACE_Null_Caching_Strategy
+{
+
+public:
+
+ // = Traits.
+ typedef ATTRIBUTES CACHING_ATTRIBUTES;
+
+ // = Strategy methods. All are NO_OP methods!!!
+
+ /// Accessor method.
+ ATTRIBUTES attributes (void);
+
+ // = Accessor methods for the percentage of entries to purge.
+ double purge_percent (void);
+
+ void purge_percent (double percentage);
+
+ // = Strategy related Operations
+
+ /// Notification for an item getting bound into the cache.
+ int notify_bind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs find
+ /// method call
+ int notify_find (int result,
+ ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs unbind
+ /// method call
+ int notify_unbind (int result,
+ const ATTRIBUTES &attr);
+
+ /// This method acts as a notification about the CONTAINERs trybind
+ /// method call
+ int notify_trybind (int result,
+ ATTRIBUTES &attr);
+
+ /// Notification for an item getting bound again into the cache.
+ int notify_rebind (int result,
+ const ATTRIBUTES &attr);
+
+ /// Purge the cache.
+ CACHING_UTILITY &caching_utility (void);
+
+ /// Dumps the state of the object.
+ void dump (void) const;
+
+private:
+
+ /// This is the helper class which will decide and expunge entries
+ /// from the cache.
+ CACHING_UTILITY caching_utility_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Caching_Strategies_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Caching_Strategies_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Caching_Strategies_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* CACHING_STRATEGIES_H */
diff --git a/ace/Connection/Caching_Strategies_T.i b/ace/Connection/Caching_Strategies_T.i
new file mode 100644
index 00000000000..b57b9fc4f38
--- /dev/null
+++ b/ace/Connection/Caching_Strategies_T.i
@@ -0,0 +1,448 @@
+/* -*-C++-*- */
+//$Id$
+
+//////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::ACE_Caching_Strategy_Adapter (IMPLEMENTATION *implementation,
+ int delete_implementation)
+ : implementation_ (implementation),
+ delete_implementation_ (delete_implementation)
+{
+ if (this->implementation_ == 0)
+ {
+ ACE_NEW (this->implementation_,
+ IMPLEMENTATION);
+ this->delete_implementation_ = 1;
+ }
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::~ACE_Caching_Strategy_Adapter (void)
+{
+ if (this->delete_implementation_)
+ {
+ delete this->implementation_;
+ this->delete_implementation_ = 0;
+ this->implementation_ = 0;
+ }
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE ATTRIBUTES
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::attributes (void)
+{
+ return this->implementation_->attributes ();
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE double
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::purge_percent (void)
+{
+ return this->implementation_->purge_percent ();
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE void
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::purge_percent (double percentage)
+{
+ this->implementation_->purge_percent (percentage);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE int
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::notify_bind (int result,
+ const ATTRIBUTES &attr)
+{
+ return this->implementation_->notify_bind (result,
+ attr);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE int
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::notify_find (int result,
+ ATTRIBUTES &attr)
+{
+ return this->implementation_->notify_find (result,
+ attr);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE int
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::notify_unbind (int result,
+ const ATTRIBUTES &attr)
+{
+ return this->implementation_->notify_unbind (result,
+ attr);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE int
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::notify_trybind (int result,
+ ATTRIBUTES &attr)
+{
+ return this->implementation_->notify_trybind (result,
+ attr);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE int
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::notify_rebind (int result,
+ const ATTRIBUTES &attr)
+{
+ return this->implementation_->notify_rebind (result,
+ attr);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE IMPLEMENTATION &
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::implementation (void)
+{
+ return *this->implementation_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE CACHING_UTILITY &
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::caching_utility (void)
+{
+ return this->implementation_->caching_utility ();
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY, class IMPLEMENTATION> ACE_INLINE void
+ACE_Caching_Strategy_Adapter<ATTRIBUTES, CACHING_UTILITY, IMPLEMENTATION>::dump (void) const
+{
+ ACE_TRACE ("ACE_Caching_Strategy_Adapter::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE ATTRIBUTES
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::attributes (void)
+{
+ return this->timer_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE double
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (void)
+{
+ return this->purge_percent_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (double percentage)
+{
+ this->purge_percent_ = percentage;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_bind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ if (result == 0)
+ ++this->timer_;
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_find (int result,
+ ATTRIBUTES &attr)
+{
+ if (result == 0)
+ {
+ attr = this->timer_;
+ ++this->timer_;
+ }
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_unbind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_trybind (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_rebind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ if (result == 0)
+ ++this->timer_;
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE CACHING_UTILITY &
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::caching_utility (void)
+{
+ return this->caching_utility_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::dump (void) const
+{
+ ACE_TRACE ("ACE_LRU_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("timer_ = %d "), this->timer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE ATTRIBUTES
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::attributes (void)
+{
+ return 0;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE double
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (void)
+{
+ return this->purge_percent_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (double percentage)
+{
+ this->purge_percent_ = percentage;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_bind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_find (int result,
+ ATTRIBUTES &attr)
+{
+ if (result == 0)
+ ++attr;
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_trybind (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_rebind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_unbind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE CACHING_UTILITY &
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::caching_utility (void)
+{
+ return this->caching_utility_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_LFU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::dump (void) const
+{
+ ACE_TRACE ("ACE_LFU_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE ATTRIBUTES
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::attributes (void)
+{
+ return this->order_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE double
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (void)
+{
+ return this->purge_percent_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (double percentage)
+{
+ this->purge_percent_ = percentage;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_bind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ if (result == 0)
+ ++this->order_;
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_find (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_unbind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_trybind (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_rebind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ if (result == 0)
+ ++this->order_;
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE CACHING_UTILITY &
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::caching_utility (void)
+{
+ return this->caching_utility_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_FIFO_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("order_ = %d "), this->order_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE ATTRIBUTES
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::attributes (void)
+{
+ return 0;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE double
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (void)
+{
+ return 0;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::purge_percent (double percentage)
+{
+ ACE_UNUSED_ARG (percentage);
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_bind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_find (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_unbind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_trybind (int result,
+ ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE int
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::notify_rebind (int result,
+ const ATTRIBUTES &attr)
+{
+ ACE_UNUSED_ARG (attr);
+
+ return result;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE CACHING_UTILITY &
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::caching_utility (void)
+{
+ return this->caching_utility_;
+}
+
+template<class ATTRIBUTES, class CACHING_UTILITY> ACE_INLINE void
+ACE_Null_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>::dump (void) const
+{
+ ACE_TRACE ("ACE_Null_Caching_Strategy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+//////////////////////////////////////////////////////////////////////////////////
diff --git a/ace/Connection/Connector.cpp b/ace/Connection/Connector.cpp
new file mode 100644
index 00000000000..2debc2b48b1
--- /dev/null
+++ b/ace/Connection/Connector.cpp
@@ -0,0 +1,952 @@
+// Connector.cpp
+// $Id$
+
+#ifndef ACE_CONNECTOR_C
+#define ACE_CONNECTOR_C
+
+#include "ace/Connector.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Connector, "$Id$")
+
+// Shorthand names.
+#define SVH SVC_HANDLER
+#define PR_CO_1 ACE_PEER_CONNECTOR_1
+#define PR_CO_2 ACE_PEER_CONNECTOR_2
+#define PR_AD ACE_PEER_CONNECTOR_ADDR
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Connector)
+
+template <class SVH, PR_CO_1> void
+ACE_Connector<SVH, PR_CO_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nclosing_ = %d"), this->closing_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nflags_ = %d"), this->flags_));
+ this->handler_map_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Bridge method for creating a SVC_HANDLER. The strategy for
+// creating a SVC_HANDLER are configured into the Acceptor via it's
+// <creation_strategy_>. The default is to create a new SVC_HANDLER.
+// However, subclasses can override this strategy to perform
+// SVC_HANDLER creation in any way that they like (such as creating
+// subclass instances of SVC_HANDLER, using a singleton, dynamically
+// linking the handler, etc.).
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::make_svc_handler");
+
+ if (sh == 0)
+ ACE_NEW_RETURN (sh,
+ SVH,
+ -1);
+
+ // Set the reactor of the newly created <SVC_HANDLER> to the same
+ // reactor that this <Connector> is using.
+ if (this->reactor ())
+ sh->reactor (this->reactor ());
+ return 0;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::activate_svc_handler");
+ // No errors initially
+ int error = 0;
+
+ // See if we should enable non-blocking I/O on the <svc_handler>'s
+ // peer.
+ if (ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK) != 0)
+ {
+ if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
+ error = 1;
+ }
+ // Otherwise, make sure it's disabled by default.
+ else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
+ error = 1;
+
+ // We are connected now, so try to open things up.
+ if (error || svc_handler->open ((void *) this) == -1)
+ {
+ // Make sure to close down the <svc_handler> to avoid descriptor
+ // leaks.
+ svc_handler->close (0);
+ return -1;
+ }
+ else
+ return 0;
+}
+
+template <class SVH, PR_CO_1> ACE_PEER_CONNECTOR &
+ACE_Connector<SVH, PR_CO_2>::connector (void) const
+{
+ return ACE_const_cast (ACE_PEER_CONNECTOR &, this->connector_);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect_svc_handler (SVC_HANDLER *&svc_handler,
+ const PR_AD &remote_addr,
+ ACE_Time_Value *timeout,
+ const PR_AD &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::connect_svc_handler");
+
+ return this->connector_.connect (svc_handler->peer (),
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect_svc_handler (SVC_HANDLER *&svc_handler,
+ SVC_HANDLER *&sh_copy,
+ const PR_AD &remote_addr,
+ ACE_Time_Value *timeout,
+ const PR_AD &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::connect_svc_handler");
+
+ sh_copy = svc_handler;
+ return this->connector_.connect (svc_handler->peer (),
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::open (ACE_Reactor *r, int flags)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::open");
+ this->reactor (r);
+ this->flags_ = flags;
+ this->closing_ = 0;
+ return 0;
+}
+
+template <class SVH, PR_CO_1>
+ACE_Connector<SVH, PR_CO_2>::ACE_Connector (ACE_Reactor *r, int flags)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::ACE_Connector");
+ (void) this->open (r, flags);
+}
+
+template <class SVH>
+ACE_Svc_Tuple<SVH>::ACE_Svc_Tuple (SVC_HANDLER *sh,
+ ACE_HANDLE handle,
+ const void *arg,
+ long id)
+ : svc_handler_ (sh),
+ handle_ (handle),
+ arg_ (arg),
+ cancellation_id_ (id)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::ACE_Svc_Tuple");
+}
+
+template <class SVH> SVC_HANDLER *
+ACE_Svc_Tuple<SVH>::svc_handler (void)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::svc_handler");
+ return this->svc_handler_;
+}
+
+template <class SVH> const void *
+ACE_Svc_Tuple<SVH>::arg (void)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::arg");
+ return this->arg_;
+}
+
+template <class SVH> void
+ACE_Svc_Tuple<SVH>::arg (const void *v)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::arg");
+ this->arg_ = v;
+}
+
+template <class SVH> ACE_HANDLE
+ACE_Svc_Tuple<SVH>::handle (void)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::handle");
+ return this->handle_;
+}
+
+template <class SVH> void
+ACE_Svc_Tuple<SVH>::handle (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::handle");
+ this->handle_ = h;
+}
+
+template <class SVH> long
+ACE_Svc_Tuple<SVH>::cancellation_id (void)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::cancellation_id");
+ return this->cancellation_id_;
+}
+
+template <class SVH> void
+ACE_Svc_Tuple<SVH>::cancellation_id (long id)
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::cancellation_id");
+ this->cancellation_id_ = id;
+}
+
+template <class SVH> void
+ACE_Svc_Tuple<SVH>::dump (void) const
+{
+ ACE_TRACE ("ACE_Svc_Tuple<SVH>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("svc_handler_ = %x"), this->svc_handler_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\narg_ = %x"), this->arg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncancellation_id_ = %d"), this->cancellation_id_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// This method is called if a connection times out before completing.
+// In this case, we call our cleanup_AST() method to cleanup the
+// descriptor from the ACE_Connector's table.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::handle_timeout");
+ AST *ast = 0;
+
+ if (this->cleanup_AST (((AST *) arg)->handle (),
+ ast) == -1)
+ return -1;
+ else
+ {
+ ACE_ASSERT (((AST *) arg) == ast);
+
+ // We may need this seemingly unnecessary assignment to work
+ // around a bug with MSVC++?
+ SVH *sh = ast->svc_handler ();
+
+ // Forward to the SVC_HANDLER the <arg> that was passed in as a
+ // magic cookie during ACE_Connector::connect(). This gives the
+ // SVC_HANDLER an opportunity to take corrective action (e.g.,
+ // wait a few milliseconds and try to reconnect again.
+ if (sh->handle_timeout (tv, ast->arg ()) == -1)
+ sh->handle_close (sh->get_handle (), ACE_Event_Handler::TIMER_MASK);
+
+ delete ast;
+ return 0;
+ }
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::cleanup_AST (ACE_HANDLE handle,
+ ACE_Svc_Tuple<SVH> *&ast)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::cleanup_AST");
+
+ // Locate the ACE_Svc_Handler corresponding to the socket
+ // descriptor.
+ if (this->handler_map_.find (handle, ast) == -1)
+ {
+ // Error, entry not found in map.
+ errno = ENOENT;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p %d not found in map\n"),
+ ACE_LIB_TEXT ("find"),
+ handle),
+ -1);
+ }
+
+ // Try to remove from ACE_Timer_Queue but if it's not there we
+ // ignore the error.
+ this->reactor ()->cancel_timer (ast->cancellation_id ());
+
+ // Remove ACE_HANDLE from ACE_Reactor.
+ this->reactor ()->remove_handler
+ (handle, ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL);
+
+ // Remove ACE_HANDLE from the map.
+ this->handler_map_.unbind (handle);
+
+ return 0;
+}
+
+// Called when a failure occurs during asynchronous connection
+// establishment. Simply delegate all work to this->handle_output().
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::handle_input (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::handle_input");
+ AST *ast = 0;
+
+ if (this->cleanup_AST (h, ast) != -1)
+ {
+ ast->svc_handler ()->close (0);
+ delete ast;
+ }
+ return 0; // Already removed from the ACE_Reactor.
+}
+
+// Finalize a connection established in non-blocking mode. When a
+// non-blocking connect *succeeds* the descriptor becomes enabled for
+// writing... Likewise, it is generally the case that when a
+// non-blocking connect *fails* the descriptor becomes enabled for
+// reading.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::handle_output (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::handle_output");
+ AST *ast = 0;
+
+ if (this->cleanup_AST (handle, ast) == -1)
+ return 0;
+
+ ACE_ASSERT (ast != 0); // This shouldn't happen!
+
+ // Try to find out if the reactor uses event associations for the
+ // handles it waits on. If so we need to reset it.
+ int reset_new_handle = this->reactor ()->uses_event_associations ();
+
+ if (reset_new_handle)
+ this->connector_.reset_new_handle (handle);
+
+ // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER.
+ ast->svc_handler ()->set_handle (handle);
+
+ PR_AD raddr;
+
+ // Check to see if we're connected.
+ if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1)
+ this->activate_svc_handler (ast->svc_handler ());
+ else // Somethings gone wrong, so close down...
+ {
+#if defined (ACE_WIN32)
+ ACE_DEBUG ((LM_DEBUG, "errno %d; Sleeping to retry get_remote_addr\n", errno));
+ // Win32 (at least prior to Windows 2000) has a timing problem.
+ // If you check to see if the connection has completed too fast,
+ // it will fail - so wait 35 milliseconds to let it catch up.
+ ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY);
+ ACE_OS::sleep (tv);
+ if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1)
+ this->activate_svc_handler (ast->svc_handler ());
+ else // do the svc handler close below...
+#endif /* ACE_WIN32 */
+ ast->svc_handler ()->close (0);
+ }
+ delete ast;
+ return 0;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::handle_exception (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::handle_exception");
+
+ return this->handle_output (h);
+}
+
+// Initiate connection to peer.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect (SVH *&sh,
+ const PR_AD &remote_addr,
+ const ACE_Synch_Options &synch_options,
+ const PR_AD &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ return this->connect_i (sh,
+ 0,
+ remote_addr,
+ synch_options,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect (SVH *&sh,
+ SVH *&sh_copy,
+ const PR_AD &remote_addr,
+ const ACE_Synch_Options &synch_options,
+ const PR_AD &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ return this->connect_i (sh,
+ &sh_copy,
+ remote_addr,
+ synch_options,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect_i (SVH *&sh,
+ SVH **sh_copy,
+ const PR_AD &remote_addr,
+ const ACE_Synch_Options &synch_options,
+ const PR_AD &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::connect_i");
+
+ // If the user hasn't supplied us with a <SVC_HANDLER> we'll use the
+ // factory method to create one. Otherwise, things will remain as
+ // they are...
+ if (this->make_svc_handler (sh) == -1)
+ return -1;
+
+ ACE_Time_Value *timeout;
+ int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
+
+ if (use_reactor)
+ timeout = (ACE_Time_Value *) &ACE_Time_Value::zero;
+ else
+ timeout = (ACE_Time_Value *) synch_options.time_value ();
+
+ int result;
+ if (sh_copy == 0)
+ result = this->connect_svc_handler (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+ else
+ result = this->connect_svc_handler (sh,
+ *sh_copy,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+
+ // Delegate to connection strategy.
+ if (result == -1)
+ {
+ if (use_reactor && errno == EWOULDBLOCK)
+ {
+ // If the connection hasn't completed and we are using
+ // non-blocking semantics then register ourselves with the
+ // ACE_Reactor so that it will call us back when the
+ // connection is complete or we timeout, whichever comes
+ // first...
+ int result;
+
+ if (sh_copy == 0)
+ result = this->create_AST (sh, synch_options);
+ else
+ result = this->create_AST (*sh_copy, synch_options);
+
+ // If for some reason the <create_AST> call failed, then
+ // <errno> will be set to the new error. If the call
+ // succeeds, however, we need to make sure that <errno>
+ // remains set to <EWOULDBLOCK>.
+ if (result == 0)
+ errno = EWOULDBLOCK;
+ }
+ else
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ // Make sure to close down the Channel to avoid descriptor
+ // leaks.
+ if (sh_copy == 0)
+ {
+ if (sh)
+ sh->close (0);
+ }
+ else if (*sh_copy)
+ (*sh_copy)->close (0);
+ }
+ return -1;
+ }
+ else
+ // Activate immediately if we are connected.
+ return this->activate_svc_handler (sh);
+}
+
+// Initiate connection to peer.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::connect_n (size_t n,
+ SVH *sh[],
+ PR_AD remote_addrs[],
+ ACE_TCHAR *failed_svc_handlers,
+ const ACE_Synch_Options &synch_options)
+{
+ int result = 0;
+
+ for (size_t i = 0; i < n; i++)
+ {
+ if (this->connect (sh[i], remote_addrs[i], synch_options) == -1
+ && !(synch_options[ACE_Synch_Options::USE_REACTOR]
+ && errno == EWOULDBLOCK))
+ {
+ result = -1;
+ if (failed_svc_handlers != 0)
+ // Mark this entry as having failed.
+ failed_svc_handlers[i] = 1;
+ }
+ else if (failed_svc_handlers != 0)
+ // Mark this entry as having succeeded.
+ failed_svc_handlers[i] = 0;
+ }
+
+ return result;
+}
+
+// Cancel a <svc_handler> that was started asynchronously.
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::cancel (SVH *sh)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::cancel");
+ MAP_ITERATOR mi (this->handler_map_);
+
+ for (MAP_ENTRY *me = 0;
+ mi.next (me) != 0;
+ mi.advance ())
+ if (me->int_id_->svc_handler () == sh)
+ {
+ AST *ast = 0;
+ this->cleanup_AST (me->ext_id_, ast);
+ delete ast;
+ return 0;
+ }
+
+ return -1;
+}
+
+// Register the pending SVC_HANDLER with the map so that it can be
+// activated later on when the connection complets.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::create_AST (SVH *sh,
+ const ACE_Synch_Options &synch_options)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::create_AST");
+ ACE_HANDLE handle = sh->get_handle ();
+ AST *ast;
+
+ ACE_NEW_RETURN (ast,
+ AST (sh,
+ handle,
+ synch_options.arg (), -1),
+ -1);
+
+ // Register this with the reactor for connection events.
+ ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK;
+
+ // Bind ACE_Svc_Tuple with the ACE_HANDLE we're trying to connect.
+ if (this->handler_map_.bind (handle, ast) == -1)
+ goto fail1;
+ else if (this->reactor ()->register_handler (handle,
+ this,
+ mask) == -1)
+ goto fail2;
+ // If we're starting connection under timer control then we need to
+ // schedule a timeout with the ACE_Reactor.
+ else
+ {
+ ACE_Time_Value *tv =
+ ACE_const_cast (ACE_Time_Value *,
+ synch_options.time_value ());
+ if (tv != 0)
+ {
+ int cancellation_id =
+ this->reactor ()->schedule_timer
+ (this,
+ (const void *) ast,
+ *tv);
+ if (cancellation_id == -1)
+ goto fail3;
+
+ ast->cancellation_id (cancellation_id);
+ return 0;
+ }
+ else
+ return 0; // Ok, everything worked just fine...
+ }
+
+ // Undo previous actions using the ol' "goto label and fallthru"
+ // trick...
+fail3:
+ this->reactor ()->remove_handler
+ (this, mask | ACE_Event_Handler::DONT_CALL);
+ /* FALLTHRU */
+fail2:
+ this->handler_map_.unbind (handle);
+ /* FALLTHRU */
+fail1:
+
+ // Close the svc_handler
+ sh->close (0);
+
+ delete ast;
+ return -1;
+}
+
+// Terminate the Client ACE_Connector by iterating over any
+// unconnected ACE_Svc_Handler's and removing them from the
+// ACE_Reactor. Note that we can't call handle_close() back at this
+// point since we own these things and we'll just get called
+// recursively!
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::close (void)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::close");
+ return this->handle_close ();
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::handle_close");
+
+ if (this->reactor () != 0 && this->closing_ == 0)
+ {
+ // We're closing down now, so make sure not to call ourselves
+ // recursively via other calls to handle_close() (e.g., from the
+ // Timer_Queue).
+ this->closing_ = 1;
+
+ for (;;)
+ {
+ // Create an iterator.
+ MAP_ITERATOR iterator = this->handler_map_.begin ();
+
+ // If we reach the end of the map, break the loop.
+ if (iterator == this->handler_map_.end ())
+ break;
+
+ // Get the first handle.
+ ACE_HANDLE handle = (*iterator).ext_id_;
+
+ // Clean it up.
+ AST *ast = 0;
+ this->cleanup_AST (handle, ast);
+
+ // Close the svc_handler.
+ ast->svc_handler ()->close (0);
+
+ // Zap the ast.
+ delete ast;
+ }
+ }
+
+ return 0;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::fini (void)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::fini");
+
+ // Make sure to call close here since our destructor might not be
+ // called if we're being dynamically linked via the svc.conf.
+ this->handler_map_.close ();
+
+ // Make sure we call our handle_close(), not a subclass's!
+ return ACE_Connector<SVH, PR_CO_2>::handle_close ();
+}
+
+// Hook called by the explicit dynamic linking facility.
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::init (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::init");
+ return -1;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::suspend (void)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::suspend");
+ return -1;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::resume (void)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::resume");
+ return -1;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Connector<SVH, PR_CO_2>::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::info");
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s\t %s"),
+ ACE_LIB_TEXT ("ACE_Connector"),
+ ACE_LIB_TEXT ("# connector factory\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strsncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+template <class SVH, PR_CO_1>
+ACE_Connector<SVH, PR_CO_2>::~ACE_Connector (void)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::~ACE_Connector");
+ // We will call our handle_close(), not a subclass's, due to the way
+ // that C++ destructors work.
+ this->handle_close ();
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::open (ACE_Reactor *r, int flags)
+{
+ ACE_TRACE ("ACE_Strategy_Connector<SVH, PR_CO_2>::open");
+ return this->open (r, 0, 0, 0, flags);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::open
+ (ACE_Reactor *r,
+ ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ int flags)
+{
+ ACE_TRACE ("ACE_Strategy_Connector<SVH, PR_CO_2>::open");
+
+ this->reactor (r);
+
+ // @@ Not implemented yet.
+ // this->flags_ = flags;
+ ACE_UNUSED_ARG (flags);
+
+ // Initialize the creation strategy.
+
+ // First we decide if we need to clean up.
+ if (this->creation_strategy_ != 0 &&
+ this->delete_creation_strategy_ != 0 &&
+ cre_s != 0)
+ {
+ delete this->creation_strategy_;
+ this->creation_strategy_ = 0;
+ this->delete_creation_strategy_ = 0;
+ }
+
+ if (cre_s != 0)
+ this->creation_strategy_ = cre_s;
+ else if (this->creation_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->creation_strategy_,
+ CREATION_STRATEGY,
+ -1);
+ this->delete_creation_strategy_ = 1;
+ }
+
+
+ // Initialize the accept strategy.
+
+ if (this->connect_strategy_ != 0 &&
+ this->delete_connect_strategy_ != 0 &&
+ conn_s != 0)
+ {
+ delete this->connect_strategy_;
+ this->connect_strategy_ = 0;
+ this->delete_connect_strategy_ = 0;
+ }
+
+ if (conn_s != 0)
+ this->connect_strategy_ = conn_s;
+ else if (this->connect_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->connect_strategy_,
+ CONNECT_STRATEGY,
+ -1);
+ this->delete_connect_strategy_ = 1;
+ }
+
+ // Initialize the concurrency strategy.
+
+ if (this->concurrency_strategy_ != 0 &&
+ this->delete_concurrency_strategy_ != 0 &&
+ con_s != 0)
+ {
+ delete this->concurrency_strategy_;
+ this->concurrency_strategy_ = 0;
+ this->delete_concurrency_strategy_ = 0;
+ }
+
+ if (con_s != 0)
+ this->concurrency_strategy_ = con_s;
+ else if (this->concurrency_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->concurrency_strategy_,
+ CONCURRENCY_STRATEGY,
+ -1);
+ this->delete_concurrency_strategy_ = 1;
+ }
+
+ return 0;
+}
+
+template <class SVH, PR_CO_1>
+ACE_Strategy_Connector<SVH, PR_CO_2>::ACE_Strategy_Connector
+ (ACE_Reactor *reactor,
+ ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ int flags)
+ : creation_strategy_ (0),
+ delete_creation_strategy_ (0),
+ connect_strategy_ (0),
+ delete_connect_strategy_ (0),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (0)
+{
+ ACE_TRACE ("ACE_Connector<SVH, PR_CO_2>::ACE_Strategy_Connector");
+
+ if (this->open (reactor, cre_s, conn_s, con_s, flags) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_Strategy_Connector::ACE_Strategy_Connector")));
+}
+
+template <class SVH, PR_CO_1>
+ACE_Strategy_Connector<SVH, PR_CO_2>::~ACE_Strategy_Connector (void)
+{
+ ACE_TRACE ("ACE_Strategy_Connector<SVH, PR_CO_2>::~ACE_Strategy_Connector");
+
+ // Close down
+ this->close ();
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::close (void)
+{
+ if (this->delete_creation_strategy_)
+ delete this->creation_strategy_;
+ this->delete_creation_strategy_ = 0;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_connect_strategy_)
+ delete this->connect_strategy_;
+ this->delete_connect_strategy_ = 0;
+ this->connect_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = 0;
+ this->concurrency_strategy_ = 0;
+
+ return SUPER::close ();
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ return this->creation_strategy_->make_svc_handler (sh);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::connect_svc_handler
+ (SVH *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ return this->connect_strategy_->connect_svc_handler (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::connect_svc_handler
+ (SVH *&sh,
+ SVH *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ return this->connect_strategy_->connect_svc_handler (sh,
+ sh_copy,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVH, PR_CO_1> int
+ACE_Strategy_Connector<SVH, PR_CO_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
+{
+ return this->concurrency_strategy_->activate_svc_handler (svc_handler, this);
+}
+
+template <class SVH, PR_CO_1> ACE_Creation_Strategy<SVC_HANDLER> *
+ACE_Strategy_Connector<SVH, PR_CO_2>::creation_strategy (void) const
+{
+ return this->creation_strategy_;
+}
+
+template <class SVH, PR_CO_1> ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *
+ACE_Strategy_Connector<SVH, PR_CO_2>::connect_strategy (void) const
+{
+ return this->connect_strategy_;
+}
+
+template <class SVH, PR_CO_1> ACE_Concurrency_Strategy<SVC_HANDLER> *
+ACE_Strategy_Connector<SVH, PR_CO_2>::concurrency_strategy (void) const
+{
+ return this->concurrency_strategy_;
+}
+
+#undef SVH
+#undef PR_CO_1
+#undef PR_CO_2
+#endif /* ACE_CONNECTOR_C */
diff --git a/ace/Connection/Connector.h b/ace/Connection/Connector.h
new file mode 100644
index 00000000000..5def25cba94
--- /dev/null
+++ b/ace/Connection/Connector.h
@@ -0,0 +1,531 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Connector.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_CONNECTOR_H
+#define ACE_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Object.h"
+#include "ace/Map_Manager.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Strategies_T.h"
+
+/**
+ * @class ACE_Svc_Tuple
+ *
+ * @brief Holds the ACE_Svc_Handler and its argument and
+ * <ACE_Timer_Handle> until an asynchronous connection completes.
+ *
+ * This is a no-brainer...
+ */
+template <class SVC_HANDLER>
+class ACE_Svc_Tuple
+{
+public:
+ // = Initialization methods.
+ ACE_Svc_Tuple (SVC_HANDLER *,
+ ACE_HANDLE,
+ const void * = 0,
+ long timer_id = -1);
+
+ // = Get SVC_HANDLER.
+ SVC_HANDLER *svc_handler (void);
+
+ // = Get/set handle.
+ /// Get handle.
+ /// Set handle.
+ ACE_HANDLE handle (void);
+ void handle (ACE_HANDLE);
+
+ // = Get/set argument.
+ /// Get argument.
+ /// Set argument.
+ const void *arg (void);
+ void arg (const void *);
+
+ // = Set/get timer cancellation handle.
+ /// Get cancellation id.
+ /// Set cancellation id.
+ long cancellation_id (void);
+ void cancellation_id (long timer_id);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Associated SVC_HANDLER.
+ SVC_HANDLER *svc_handler_;
+
+ /// IPC <HANDLE> that we are trying to connect.
+ ACE_HANDLE handle_;
+
+ /// Associated argument.
+ const void *arg_;
+
+ /// Associated cancellation id.
+ long cancellation_id_;
+};
+
+/**
+ * @class ACE_Connector
+ *
+ * @brief Generic factory for actively connecting clients and creating
+ * service handlers (SVC_HANDLERs).
+ *
+ * Implements the strategy for actively establishing connections
+ * with clients. An ACE_Connector is parameterized by concrete
+ * types that conform to the interfaces of PEER_CONNECTOR and
+ * SVC_HANDLER. The PEER_CONNECTOR is instantiated with a
+ * transport mechanism that passively establishes connections.
+ * The SVC_HANDLER is instantiated with a concrete type that
+ * performs the application-specific service. An ACE_Connector
+ * inherits from ACE_Service_Object, which in turn inherits from
+ * ACE_Event_Handler. This enables the ACE_Reactor to dispatch
+ * the ACE_Connector's handle_output method when connections
+ * complete asynchronously. The handle_output method performs
+ * the connector's active connection establishment and service
+ * activation strategy.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_Connector : public ACE_Service_Object
+{
+public:
+ // = Initialization and termination methods.
+
+ // typedef ACE_TYPENAME ACE_PEER_CONNECTOR_ADDR PEER_ADDR;
+#if defined (ACE_HAS_TYPENAME_KEYWORD)
+ typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF;
+#endif /* ACE_HAS_TYPENAME_KEYWORD */
+
+ typedef ACE_TYPENAME _ACE_PEER_CONNECTOR::PEER_ADDR
+ ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR;
+
+ /**
+ * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s
+ * should be initialized prior to being activated. Right now, the
+ * only flag that is processed is <ACE_NONBLOCK>, which enabled
+ * non-blocking I/O on the <SVC_HANDLER> when it is opened.
+ */
+ ACE_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
+ int flags = 0);
+
+ /**
+ * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s
+ * should be initialized prior to being activated. Right now, the
+ * only flag that is processed is <ACE_NONBLOCK>, which enabled
+ * non-blocking I/O on the <SVC_HANDLER> when it is opened.
+ */
+ virtual int open (ACE_Reactor *r = ACE_Reactor::instance (),
+ int flags = 0);
+
+ /// Shutdown a connector and release resources.
+ virtual ~ACE_Connector (void);
+
+ // = Connection establishment methods.
+
+ /**
+ * Initiate connection of <svc_handler> to peer at <remote_addr>
+ * using <synch_options>. If the caller wants to designate the
+ * selected <local_addr> they can (and can also insist that the
+ * <local_addr> be reused by passing a value <reuse_addr> ==
+ * 1). <flags> and <perms> can be used to pass any flags that are
+ * needed to perform specific operations such as opening a file
+ * within connect with certain permissions. If the connection fails
+ * the <close> hook on the <svc_handler> will be called
+ * automatically to prevent resource leaks.
+ */
+ virtual int connect (SVC_HANDLER *&svc_handler,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr
+ = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * This is a variation on the previous <connect> method. On cached
+ * connectors the <svc_handler_hint> variable can be used as a hint
+ * for future lookups. Since this variable is modified in the
+ * context of the internal cache its use is thread-safe. But the
+ * actual svc_handler for the current connection is returned in the
+ * second parameter <svc_handler>. If the connection fails the
+ * <close> hook on the <svc_handler> will be called automatically to
+ * prevent resource leaks.
+ */
+ virtual int connect (SVC_HANDLER *&svc_handler_hint,
+ SVC_HANDLER *&svc_handler,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr
+ = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * Initiate connection of <n> <svc_handlers> to peers at
+ * <remote_addrs> using <synch_options>. Returns -1 if failure
+ * occurs and 0 otherwise. If <failed_svc_handlers> is non-NULL, a
+ * 1 is placed in the corresponding index of <failed_svc_handler>
+ * for each <svc_handlers[i]> that failed to connect, else a 0 is
+ * placed in that index.
+ */
+ virtual int connect_n (size_t n,
+ SVC_HANDLER *svc_handlers[],
+ ACE_PEER_CONNECTOR_ADDR remote_addrs[],
+ ACE_TCHAR *failed_svc_handlers = 0,
+ const ACE_Synch_Options &synch_options =
+ ACE_Synch_Options::defaults);
+
+ /**
+ * Cancel a <svc_handler> that was started asynchronously. Note that
+ * this is the only case when the Connector does not actively close
+ * the <svc_handler>. It is left up to the caller of <cancel> to
+ * decide the fate of the <svc_handler>.
+ */
+ virtual int cancel (SVC_HANDLER *svc_handler);
+
+ /// Close down the Connector
+ virtual int close (void);
+
+ /// Return the underlying PEER_ACCEPTOR object.
+ virtual ACE_PEER_CONNECTOR &connector (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Helpful typedefs.
+
+ typedef ACE_Svc_Tuple<SVC_HANDLER>
+ AST;
+
+ typedef ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_SYNCH_RW_MUTEX>
+ MAP_MANAGER;
+ typedef ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_SYNCH_RW_MUTEX>
+ MAP_ITERATOR;
+ typedef ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *>
+ MAP_ENTRY;
+
+ // = The following two methods define the Connector's strategies for
+ // creating, connecting, and activating SVC_HANDLER's, respectively.
+
+ /**
+ * Bridge method for creating a SVC_HANDLER. The default is to
+ * create a new SVC_HANDLER only if <sh> == 0, else <sh> is
+ * unchanged. However, subclasses can override this policy to
+ * perform SVC_HANDLER creation in any way that they like (such as
+ * creating subclass instances of SVC_HANDLER, using a singleton,
+ * dynamically linking the handler, etc.). Returns -1 if failure,
+ * else 0.
+ */
+ virtual int make_svc_handler (SVC_HANDLER *&sh);
+
+ /**
+ * Bridge method for connecting the <svc_handler> to the
+ * <remote_addr>. The default behavior delegates to the
+ * <PEER_CONNECTOR::connect>.
+ */
+ virtual int connect_svc_handler (SVC_HANDLER *&svc_handler,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+ virtual int connect_svc_handler (SVC_HANDLER *&svc_handler,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /**
+ * Bridge method for activating a <svc_handler> with the appropriate
+ * concurrency strategy. The default behavior of this method is to
+ * activate the SVC_HANDLER by calling its <open> method (which
+ * allows the SVC_HANDLER to define its own concurrency strategy).
+ * However, subclasses can override this strategy to do more
+ * sophisticated concurrency activations (such as creating the
+ * SVC_HANDLER as an "active object" via multi-threading or
+ * multi-processing).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ /// Called by ACE_Reactor when asynchronous connections fail.
+ virtual int handle_input (ACE_HANDLE);
+
+ /// Called by ACE_Reactor when asynchronous connections succeed.
+ virtual int handle_output (ACE_HANDLE);
+
+ /// Called by ACE_Reactor when asynchronous connections complete (on
+ /// some platforms only).
+ virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // = Dynamic linking hooks.
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Calls <handle_close> to shutdown the Connector gracefully.
+ virtual int fini (void);
+
+ /// Default version returns address info in <buf>.
+ virtual int info (ACE_TCHAR **, size_t) const;
+
+ // = Demultiplexing hooks.
+ /**
+ * Terminate the Client ACE_Connector by iterating over any
+ * unconnected ACE_Svc_Handler's and removing them from the
+ * ACE_Reactor.
+ */
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// This method is called if a connection times out before
+ /// completing.
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+
+ // = Service management hooks.
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int suspend (void);
+
+ /// Default version does no work and returns -1. Must be overloaded
+ /// by application developer to do anything meaningful.
+ virtual int resume (void);
+
+ /// Creates and inserts an ACE_Svc_Tuple into the <handler_map_>.
+ /// so that we can continue accepting this connection asynchronously.
+ int create_AST (SVC_HANDLER *,
+ const ACE_Synch_Options &);
+
+ /// Cleanup the <handler_map_> and returns the appropriate
+ /// ACE_Svc_Tuple (which is 0 if there is no associated tuple).
+ int cleanup_AST (ACE_HANDLE, AST *&);
+
+ /// Implementation the <connect> methods.
+ virtual int connect_i (SVC_HANDLER *&svc_handler,
+ SVC_HANDLER **sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ const ACE_Synch_Options &synch_options,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /// Lookup table that maps an I/O handle to a SVC_HANDLER *.
+ MAP_MANAGER handler_map_;
+
+private:
+ /// This is the concrete connector factory (it keeps no state so the
+ /// <ACE_Connector> is reentrant).
+ ACE_PEER_CONNECTOR connector_;
+
+ /// Keeps track of whether we are in the process of closing (required
+ /// to avoid circular calls to <handle_close>).
+ char closing_;
+
+ /**
+ * Flags that indicate how <SVC_HANDLER>'s should be initialized
+ * prior to being activated. Right now, the only flag that is
+ * processed is <ACE_NONBLOCK>, which enabled non-blocking I/O on
+ * the <SVC_HANDLER> when it is opened.
+ */
+ int flags_;
+};
+
+/**
+ * @class ACE_Strategy_Connector
+ *
+ * @brief Abstract factory for creating a service handler
+ * (SVC_HANDLER), connecting the SVC_HANDLER, and activating the
+ * SVC_HANDLER.
+ *
+ * Implements a flexible and extensible set of strategies for
+ * actively establishing connections with clients. There are
+ * three main strategies: (1) creating a SVC_HANDLER, (2)
+ * actively initiating a new connection from the client,
+ * and (3) activating the SVC_HANDLER with a
+ * particular concurrency mechanism after the connection is established.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_Strategy_Connector : public ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+{
+public:
+ /**
+ * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s
+ * should be initialized prior to being activated. Right now, the
+ * only flag that is processed is <ACE_NONBLOCK>, which enabled
+ * non-blocking I/O on the <SVC_HANDLER> when it is opened.
+ */
+ ACE_Strategy_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
+ ACE_Creation_Strategy<SVC_HANDLER> * = 0,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
+ int flags = 0);
+
+ /**
+ * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s
+ * should be initialized prior to being activated. Right now, the
+ * only flag that is processed is <ACE_NONBLOCK>, which enabled
+ * non-blocking I/O on the <SVC_HANDLER> when it is opened.
+ * Default strategies would be created and used.
+ */
+ virtual int open (ACE_Reactor *r,
+ int flags);
+
+ /**
+ * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s
+ * should be initialized prior to being activated. Right now, the
+ * only flag that is processed is <ACE_NONBLOCK>, which enabled
+ * non-blocking I/O on the <SVC_HANDLER> when it is opened.
+ */
+ virtual int open (ACE_Reactor *r = ACE_Reactor::instance (),
+ ACE_Creation_Strategy<SVC_HANDLER> * = 0,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
+ int flags = 0);
+
+ /// Shutdown a connector and release resources.
+ virtual ~ACE_Strategy_Connector (void);
+
+ /// Close down the Connector
+ virtual int close (void);
+
+ // = Define some useful typedefs traits.
+ typedef ACE_Creation_Strategy<SVC_HANDLER>
+ CREATION_STRATEGY;
+ typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ CONNECT_STRATEGY;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER>
+ CONCURRENCY_STRATEGY;
+ typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ SUPER;
+
+ // = Strategies accessors
+ virtual ACE_Creation_Strategy<SVC_HANDLER> *creation_strategy (void) const;
+ virtual ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *connect_strategy (void) const;
+ virtual ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy (void) const;
+
+protected:
+ // = The following three methods define the <Connector>'s strategies
+ // for creating, connecting, and activating <SVC_HANDLER>'s,
+ // respectively.
+
+ /**
+ * Bridge method for creating a <SVC_HANDLER>. The strategy for
+ * creating a <SVC_HANDLER> are configured into the Connector via
+ * it's <creation_strategy_>. The default is to create a new
+ * <SVC_HANDLER> only if <sh> == 0, else <sh> is unchanged.
+ * However, subclasses can override this policy to perform
+ * <SVC_HANDLER> creation in any way that they like (such as
+ * creating subclass instances of <SVC_HANDLER>, using a singleton,
+ * dynamically linking the handler, etc.). Returns -1 if failure,
+ * else 0.
+ */
+ virtual int make_svc_handler (SVC_HANDLER *&sh);
+
+ /**
+ * Bridge method for connecting the new connection into the
+ * <SVC_HANDLER>. The default behavior delegates to the
+ * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
+ */
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /**
+ * Bridge method for connecting the new connection into the
+ * <SVC_HANDLER>. The default behavior delegates to the
+ * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
+ * <sh_copy> is used to obtain a copy of the <sh> pointer, but that
+ * can be kept in the stack; the motivation is a bit too long to
+ * include here, but basically we want to modify <sh> safely, using
+ * the internal locks in the Connect_Strategy, while saving a TSS
+ * copy in <sh_copy>, usually located in the stack.
+ */
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /**
+ * Bridge method for activating a <SVC_HANDLER> with the appropriate
+ * concurrency strategy. The default behavior of this method is to
+ * activate the <SVC_HANDLER> by calling its <open> method (which
+ * allows the <SVC_HANDLER> to define its own concurrency strategy).
+ * However, subclasses can override this strategy to do more
+ * sophisticated concurrency activations (such as creating the
+ * <SVC_HANDLER> as an "active object" via multi-threading or
+ * multi-processing).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ // = Strategy objects.
+
+ /// Creation strategy for an <Connector>.
+ CREATION_STRATEGY *creation_strategy_;
+
+ /// 1 if <Connector> created the creation strategy and thus should
+ /// delete it, else 0.
+ int delete_creation_strategy_;
+
+ /// Connect strategy for a <Connector>.
+ CONNECT_STRATEGY *connect_strategy_;
+
+ /// 1 if <Connector> created the connect strategy and thus should
+ /// delete it, else 0.
+ int delete_connect_strategy_;
+
+ /// Concurrency strategy for an <Connector>.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// 1 if <Connector> created the concurrency strategy and thus should
+ /// delete it, else 0.
+ int delete_concurrency_strategy_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Connector.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Connector.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_CONNECTOR_H */
diff --git a/ace/Connection/LOCK_SOCK_Acceptor.cpp b/ace/Connection/LOCK_SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..931216750ae
--- /dev/null
+++ b/ace/Connection/LOCK_SOCK_Acceptor.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#ifndef ACE_LOCK_SOCK_ACCEPTOR_CPP
+#define ACE_LOCK_SOCK_ACCEPTOR_CPP
+
+#include "ace/Synch.h"
+#include "ace/LOCK_SOCK_Acceptor.h"
+
+ACE_RCSID(ace, LOCK_SOCK_Acceptor, "$Id$")
+
+template <class ACE_LOCK> int
+ACE_LOCK_SOCK_Acceptor<ACE_LOCK>::accept (ACE_SOCK_Stream &stream,
+ ACE_Addr *remote_address,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_, -1);
+
+ return ACE_SOCK_Acceptor::accept (stream,
+ remote_address,
+ timeout,
+ restart,
+ reset_new_handle);
+}
+
+template <class ACE_LOCK> ACE_LOCK &
+ACE_LOCK_SOCK_Acceptor<ACE_LOCK>::lock (void)
+{
+ return this->lock_;
+}
+
+#endif /* ACE_LOCK_SOCK_ACCEPTOR_CPP */
diff --git a/ace/Connection/LOCK_SOCK_Acceptor.h b/ace/Connection/LOCK_SOCK_Acceptor.h
new file mode 100644
index 00000000000..720664e65ff
--- /dev/null
+++ b/ace/Connection/LOCK_SOCK_Acceptor.h
@@ -0,0 +1,62 @@
+
+//=============================================================================
+/**
+ * @file LOCK_SOCK_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author James Hu and Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCK_SOCK_ACCEPTOR_H
+#define ACE_LOCK_SOCK_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_LOCK_SOCK_Acceptor
+ *
+ * @brief Specialize <ACE_SOCK_Acceptor> to lock around <accept>;
+ *
+ * This class is necessary since some OS platforms (e.g.,
+ * Solaris 2.5) do not allow multiple threads/processes to
+ * simultaneously call <accept> on the same listen-mode
+ * port/socket. Thus, we need to protect against multiple
+ * concurrent accesses by using the appropriate type of lock.
+ */
+template <class ACE_LOCK>
+class ACE_LOCK_SOCK_Acceptor : public ACE_SOCK_Acceptor
+{
+public:
+ /// Accept the connection under the control of the <ACE_LOCK>.
+ int accept (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ /// Return a reference to the lock.
+ ACE_LOCK &lock (void);
+
+protected:
+ /// Type of locking mechanism.
+ ACE_LOCK lock_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/LOCK_SOCK_Acceptor.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("LOCK_SOCK_Acceptor.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_LOCK_SOCK_ACCEPTOR_H */
diff --git a/ace/Connection/POSIX_Asynch_IO.cpp b/ace/Connection/POSIX_Asynch_IO.cpp
new file mode 100644
index 00000000000..010200327b6
--- /dev/null
+++ b/ace/Connection/POSIX_Asynch_IO.cpp
@@ -0,0 +1,2912 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/POSIX_Asynch_IO.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Proactor.h"
+#include "ace/Message_Block.h"
+#include "ace/INET_Addr.h"
+#include "ace/Task_T.h"
+#include "ace/POSIX_Proactor.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/POSIX_Asynch_IO.i"
+#endif /* __ACE_INLINE__ */
+
+u_long
+ACE_POSIX_Asynch_Result::bytes_transferred (void) const
+{
+ return this->bytes_transferred_;
+}
+
+void
+ACE_POSIX_Asynch_Result::set_bytes_transferred (u_long nbytes)
+{
+ this->bytes_transferred_= nbytes;
+}
+
+const void *
+ACE_POSIX_Asynch_Result::act (void) const
+{
+ return this->act_;
+}
+
+int
+ACE_POSIX_Asynch_Result::success (void) const
+{
+ return this->success_;
+}
+
+const void *
+ACE_POSIX_Asynch_Result::completion_key (void) const
+{
+ return this->completion_key_;
+}
+
+u_long
+ACE_POSIX_Asynch_Result::error (void) const
+{
+ return this->error_;
+}
+
+void
+ACE_POSIX_Asynch_Result::set_error (u_long errcode)
+{
+ this->error_=errcode;
+}
+ACE_HANDLE
+ACE_POSIX_Asynch_Result::event (void) const
+{
+ return ACE_INVALID_HANDLE;
+}
+
+u_long
+ACE_POSIX_Asynch_Result::offset (void) const
+{
+ return this->aio_offset;
+}
+
+u_long
+ACE_POSIX_Asynch_Result::offset_high (void) const
+{
+ //
+ // @@ Support aiocb64??
+ //
+ ACE_NOTSUP_RETURN (0);
+}
+
+int
+ACE_POSIX_Asynch_Result::priority (void) const
+{
+ return this->aio_reqprio;
+}
+
+int
+ACE_POSIX_Asynch_Result::signal_number (void) const
+{
+ return this->aio_sigevent.sigev_signo;
+}
+
+int
+ACE_POSIX_Asynch_Result::post_completion (ACE_Proactor_Impl *proactor_impl)
+{
+ // Get to the platform specific implementation.
+ ACE_POSIX_Proactor *posix_proactor = ACE_dynamic_cast (ACE_POSIX_Proactor *,
+ proactor_impl);
+
+ if (posix_proactor == 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "Dynamic cast to POSIX Proactor failed\n"), -1);
+
+ // Post myself.
+ return posix_proactor->post_completion (this);
+}
+
+ACE_POSIX_Asynch_Result::~ACE_POSIX_Asynch_Result (void)
+{
+}
+
+ACE_POSIX_Asynch_Result::ACE_POSIX_Asynch_Result (ACE_Handler &handler,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ aiocb (),
+ handler_ (handler),
+ act_ (act),
+ bytes_transferred_ (0),
+ success_ (0),
+ completion_key_ (0),
+ error_ (0)
+{
+ aio_offset = offset;
+ aio_reqprio = priority;
+ aio_sigevent.sigev_signo = signal_number;
+
+ // Event is not used on POSIX.
+ ACE_UNUSED_ARG (event);
+
+ //
+ // @@ Support offset_high with aiocb64.
+ //
+ ACE_UNUSED_ARG (offset_high);
+
+ // Other fields in the <aiocb> will be initialized by the
+ // subclasses.
+}
+
+// ****************************************************************
+
+int
+ACE_POSIX_Asynch_Operation::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ this->proactor_ = proactor;
+ this->handler_ = &handler;
+ this->handle_ = handle;
+
+ // Grab the handle from the <handler> if <handle> is invalid
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ this->handle_ = this->handler_->handle ();
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+#if 0
+ // @@ If <proactor> is 0, let us not bother about getting this
+ // Proactor, we have already got the specific implementation
+ // Proactor.
+
+ // If no proactor was passed
+ if (this->proactor_ == 0)
+ {
+ // Grab the proactor from the <Service_Config> if
+ // <handler->proactor> is zero
+ this->proactor_ = this->handler_->proactor ();
+ if (this->proactor_ == 0)
+ this->proactor_ = ACE_Proactor::instance();
+ }
+#endif /* 0 */
+
+ // AIO stuff is present. So no registering.
+ ACE_UNUSED_ARG (completion_key);
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Operation::cancel (void)
+{
+ ACE_Proactor *p = this->proactor () ;
+
+ if (!p)
+ return -1;
+
+ ACE_POSIX_Proactor * p_impl = ACE_dynamic_cast
+ (ACE_POSIX_Proactor *,
+ p->implementation ());
+ if (!p_impl)
+ return -1;
+
+ // For ACE_SUN_Proactor and ACE_POSIX_AIOCB_Proactor
+ // and ACE_POSIX_SIG_Proactor now !
+ // we should call cancel_aio (this->handle_)
+ // method to cancel correctly all deferred AIOs
+
+ switch (p_impl->get_impl_type ())
+ {
+ case ACE_POSIX_Proactor::PROACTOR_SUN:
+ case ACE_POSIX_Proactor::PROACTOR_AIOCB:
+ case ACE_POSIX_Proactor::PROACTOR_SIG:
+ {
+ ACE_POSIX_AIOCB_Proactor * p_impl_aiocb = ACE_dynamic_cast
+ (ACE_POSIX_AIOCB_Proactor *,
+ p_impl);
+
+ if (! p_impl_aiocb)
+ return -1;
+
+ return p_impl_aiocb->cancel_aio (this->handle_);
+ }
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+ACE_Proactor *
+ACE_POSIX_Asynch_Operation::proactor (void) const
+{
+ return this->proactor_;
+}
+
+ACE_POSIX_Asynch_Operation::~ACE_POSIX_Asynch_Operation (void)
+{
+}
+
+ACE_POSIX_Asynch_Operation::ACE_POSIX_Asynch_Operation (void)
+ : ACE_Asynch_Operation_Impl (),
+ handler_ (0),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Proactor *
+ACE_POSIX_AIOCB_Asynch_Operation::posix_proactor (void) const
+{
+ return this->posix_aiocb_proactor_;
+}
+
+ACE_POSIX_AIOCB_Asynch_Operation::ACE_POSIX_AIOCB_Asynch_Operation (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_POSIX_Asynch_Operation (),
+ posix_aiocb_proactor_ (posix_aiocb_proactor)
+{
+}
+
+ACE_POSIX_AIOCB_Asynch_Operation::~ACE_POSIX_AIOCB_Asynch_Operation (void)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Operation::register_and_start_aio (ACE_POSIX_Asynch_Result *result,
+ int op)
+{
+ return this->posix_proactor ()->register_and_start_aio (result, op);
+}
+
+// *********************************************************************
+
+u_long
+ACE_POSIX_Asynch_Read_Stream_Result::bytes_to_read (void) const
+{
+ return this->aio_nbytes;
+}
+
+ACE_Message_Block &
+ACE_POSIX_Asynch_Read_Stream_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_Stream_Result::handle (void) const
+{
+ return this->aio_fildes;
+}
+
+ACE_POSIX_Asynch_Read_Stream_Result::ACE_POSIX_Asynch_Read_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ message_block_ (message_block)
+{
+ this->aio_fildes = handle;
+ this->aio_buf = message_block.wr_ptr ();
+ this->aio_nbytes = bytes_to_read;
+ ACE_UNUSED_ARG (event);
+}
+
+void
+ACE_POSIX_Asynch_Read_Stream_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <errno> is available in the aiocb.
+ ACE_UNUSED_ARG (error);
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_Stream::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_stream (result);
+}
+
+ACE_POSIX_Asynch_Read_Stream_Result::~ACE_POSIX_Asynch_Read_Stream_Result (void)
+{
+}
+
+// = Base class operations. These operations are here to kill
+// dominance warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Read_Stream_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_Stream_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Stream_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_Stream_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Stream_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_Stream_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Stream_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Stream_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Stream_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Stream_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// ************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Read_Stream::ACE_POSIX_AIOCB_Asynch_Read_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Stream_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Operation (posix_aiocb_proactor)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ // Create the Asynch_Result.
+ ACE_POSIX_Asynch_Read_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Read_Stream_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // we do not need shared_read anymore
+ //ssize_t return_val = this->shared_read (result);
+
+ // try to start read
+ // we will setup aio_sigevent later
+ // in ACE_POSIX_AIOCB/SIG_Proactor::register_and_start_aio ()
+
+ ssize_t return_val = this->register_and_start_aio (result, 0);
+
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_AIOCB_Asynch_Read_Stream::~ACE_POSIX_AIOCB_Asynch_Read_Stream (void)
+{
+}
+
+//int
+//ACE_POSIX_AIOCB_Asynch_Read_Stream::shared_read (ACE_POSIX_Asynch_Read_Stream_Result *result)
+//{
+//
+// result->aio_sigevent.sigev_notify = SIGEV_NONE;
+//
+// // try start read
+// return register_and_start_aio (result, 0);
+//}
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route
+// the call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_Stream::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Read_Stream::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// *********************************************************************
+
+u_long
+ACE_POSIX_Asynch_Write_Stream_Result::bytes_to_write (void) const
+{
+ return this->aio_nbytes;
+}
+
+ACE_Message_Block &
+ACE_POSIX_Asynch_Write_Stream_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_Stream_Result::handle (void) const
+{
+ return this->aio_fildes;
+}
+
+ACE_POSIX_Asynch_Write_Stream_Result::ACE_POSIX_Asynch_Write_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ message_block_ (message_block)
+{
+ this->aio_fildes = handle;
+ this->aio_buf = message_block.rd_ptr ();
+ this->aio_nbytes = bytes_to_write;
+ ACE_UNUSED_ARG (event);
+}
+
+void
+ACE_POSIX_Asynch_Write_Stream_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Get all the data copied.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <errno> is available in the aiocb.
+ ACE_UNUSED_ARG (error);
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.rd_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Stream::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_stream (result);
+}
+
+ACE_POSIX_Asynch_Write_Stream_Result::~ACE_POSIX_Asynch_Write_Stream_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Write_Stream_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_Stream_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Stream_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_Stream_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Stream_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_Stream_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Stream_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Stream_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Stream_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Stream_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Write_Stream::ACE_POSIX_AIOCB_Asynch_Write_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Stream_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Operation (posix_aiocb_proactor)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_POSIX_Asynch_Write_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Write_Stream_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // we do not need shared_write anymore
+ //ssize_t return_val = this->shared_write (result);
+
+ // try to start write
+ // we will setup aio_sigevent later
+ // in ACE_POSIX_AIOCB/SIG_Proactor::register_and_start_aio ()
+
+ ssize_t return_val = this->register_and_start_aio (result, 1);
+
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_AIOCB_Asynch_Write_Stream::~ACE_POSIX_AIOCB_Asynch_Write_Stream (void)
+{
+}
+
+//int
+//ACE_POSIX_AIOCB_Asynch_Write_Stream::shared_write (ACE_POSIX_Asynch_Write_Stream_Result *result)
+//{
+//
+// result->aio_sigevent.sigev_notify = SIGEV_NONE;
+//
+// // try start write
+// return register_and_start_aio (result, 1);
+//}
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route
+// the call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_Stream::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Write_Stream::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// *********************************************************************
+
+
+ACE_POSIX_Asynch_Read_File_Result::ACE_POSIX_Asynch_Read_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_Asynch_Read_File_Result_Impl (),
+ ACE_POSIX_Asynch_Read_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number)
+{
+ this->aio_offset = offset;
+ //
+ // @@ Use aiocb64??
+ //
+ ACE_UNUSED_ARG (offset_high);
+}
+
+void
+ACE_POSIX_Asynch_Read_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy all the data.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <errno> is available in the aiocb.
+ ACE_UNUSED_ARG (error);
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_file (result);
+}
+
+ACE_POSIX_Asynch_Read_File_Result::~ACE_POSIX_Asynch_Read_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Read_File_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_File_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Read_File_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_File_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_File_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_File_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_File_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_File_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Read_File_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Read_File_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+// The following methods belong to
+// ACE_POSIX_Asynch_Read_Stream_Result. They are here to avoid
+// dominace warnings. These methods route their call to the
+// ACE_POSIX_Asynch_Read_Stream_Result base class.
+
+u_long
+ACE_POSIX_Asynch_Read_File_Result::bytes_to_read (void) const
+{
+ return ACE_POSIX_Asynch_Read_Stream_Result::bytes_to_read ();
+}
+
+ACE_Message_Block &
+ACE_POSIX_Asynch_Read_File_Result::message_block (void) const
+{
+ return ACE_POSIX_Asynch_Read_Stream_Result::message_block ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_File_Result::handle (void) const
+{
+ return ACE_POSIX_Asynch_Read_Stream_Result::handle ();
+}
+
+int
+ACE_POSIX_Asynch_Read_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Read_File::ACE_POSIX_AIOCB_Asynch_Read_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Stream_Impl (),
+ ACE_Asynch_Read_File_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Read_Stream (posix_aiocb_proactor)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_POSIX_Asynch_Read_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Read_File_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ //ssize_t return_val = this->shared_read (result);
+ ssize_t return_val = this->register_and_start_aio (result, 0);
+
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_AIOCB_Asynch_Read_File::~ACE_POSIX_AIOCB_Asynch_Read_File (void)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_POSIX_AIOCB_Asynch_Read_Stream::read (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route
+// the call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_File::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Read_File::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// ************************************************************
+
+ACE_POSIX_Asynch_Write_File_Result::ACE_POSIX_Asynch_Write_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_Asynch_Write_File_Result_Impl (),
+ ACE_POSIX_Asynch_Write_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number)
+{
+ this->aio_offset = offset;
+ //
+ // @@ Support offset_high with aiocb64.
+ //
+ ACE_UNUSED_ARG (offset_high);
+}
+
+void
+ACE_POSIX_Asynch_Write_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <error> is available in <aio_resultp.aio_error>
+ ACE_UNUSED_ARG (error);
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.rd_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Write_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_file (result);
+}
+
+ACE_POSIX_Asynch_Write_File_Result::~ACE_POSIX_Asynch_Write_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Write_File_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_File_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Write_File_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_File_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_File_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_File_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_File_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_File_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Write_File_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Write_File_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+// The following methods belong to
+// ACE_POSIX_Asynch_Write_Stream_Result. They are here to avoid
+// dominance warnings. These methods route their call to the
+// ACE_POSIX_Asynch_Write_Stream_Result base class.
+
+u_long
+ACE_POSIX_Asynch_Write_File_Result::bytes_to_write (void) const
+{
+ return ACE_POSIX_Asynch_Write_Stream_Result::bytes_to_write ();
+}
+
+ACE_Message_Block &
+ACE_POSIX_Asynch_Write_File_Result::message_block (void) const
+{
+ return ACE_POSIX_Asynch_Write_Stream_Result::message_block ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_File_Result::handle (void) const
+{
+ return ACE_POSIX_Asynch_Write_Stream_Result::handle ();
+}
+
+int
+ACE_POSIX_Asynch_Write_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Write_File::ACE_POSIX_AIOCB_Asynch_Write_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Stream_Impl (),
+ ACE_Asynch_Write_File_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Write_Stream (posix_aiocb_proactor)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_POSIX_Asynch_Write_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Write_File_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ //ssize_t return_val = this->shared_write (result);
+ ssize_t return_val = this->register_and_start_aio (result, 1);
+
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_POSIX_AIOCB_Asynch_Write_File::~ACE_POSIX_AIOCB_Asynch_Write_File (void)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_POSIX_AIOCB_Asynch_Write_Stream::write (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route
+// the call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_File::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Write_File::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// *********************************************************************
+
+u_long
+ACE_POSIX_Asynch_Accept_Result::bytes_to_read (void) const
+{
+ return this->aio_nbytes;
+}
+
+ACE_Message_Block &
+ACE_POSIX_Asynch_Accept_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Accept_Result::listen_handle (void) const
+{
+ return this->listen_handle_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Accept_Result::accept_handle (void) const
+{
+ return this->aio_fildes;
+}
+
+ACE_POSIX_Asynch_Accept_Result::ACE_POSIX_Asynch_Accept_Result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Accept_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ message_block_ (message_block),
+ listen_handle_ (listen_handle)
+{
+ this->aio_fildes = accept_handle;
+ this->aio_nbytes = bytes_to_read;
+}
+
+void
+ACE_POSIX_Asynch_Accept_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Accept::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_accept (result);
+}
+
+ACE_POSIX_Asynch_Accept_Result::~ACE_POSIX_Asynch_Accept_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Accept_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Accept_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Accept_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Accept_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Accept_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Accept_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Accept_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Accept_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Accept_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Accept_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+int
+ACE_POSIX_Asynch_Accept_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+class ACE_Export ACE_POSIX_Asynch_Accept_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // For the POSIX implementation this class is common
+ // for all Proactors (AIOCB/SIG/SUN)
+ //
+ // = DESCRIPTION
+ //
+
+public:
+ ~ACE_POSIX_Asynch_Accept_Handler (void);
+ // Destructor.
+
+ ACE_POSIX_Asynch_Accept_Handler (ACE_Reactor* reactor,
+ ACE_POSIX_Proactor *posix_proactor);
+ // Constructor. Give the reactor so that it can activate/deactivate
+ // the handlers. Give also the proactor used here, so that the
+ // handler can send the <POSIX_Asynch_Accept> result block through
+ // <post_completion>.
+
+ int cancel_uncompleted (int flg_notify);
+ // flg_notify points whether or not we should send notification about
+ // canceled accepts
+
+
+ int register_accept_call (ACE_POSIX_Asynch_Accept_Result* result);
+ // Worker method for registering this <accept> call with the local
+ // handler. This method obtains lock to access the shared the queues.
+
+ ACE_POSIX_Asynch_Accept_Result* deregister_accept_call (void);
+ // Method for deregistering.
+
+ int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+ // Called when accept event comes up on <listen_hanlde>
+
+protected:
+ ACE_Reactor* reactor_;
+ // Reactor used by the Asynch_Accept. We need this here to enable
+ // and disable the <handle> now and then, depending on whether any
+ // <accept> is pending or no.
+
+ ACE_POSIX_Proactor *posix_proactor_;
+ // POSIX_Proactor implementation.
+
+ ACE_Unbounded_Queue<ACE_POSIX_Asynch_Accept_Result*> result_queue_;
+ // Queue of Result pointers that correspond to all the <accept>'s
+ // pending.
+
+ ACE_SYNCH_MUTEX lock_;
+ // The lock to protect the result queue which is shared. The queue
+ // is updated by main thread in the register function call and
+ // through the auxillary thread in the deregister fun. So let us
+ // mutex it.
+};
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Accept_Handler::ACE_POSIX_Asynch_Accept_Handler (ACE_Reactor* reactor,
+ ACE_POSIX_Proactor *posix_proactor)
+ : reactor_ (reactor),
+ posix_proactor_ (posix_proactor)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept_Handler::ctor");
+}
+
+ACE_POSIX_Asynch_Accept_Handler::~ACE_POSIX_Asynch_Accept_Handler (void)
+{
+ ACE_TRACE ("ACE_POSIX_Asynch_Accept_Handler::~ACE_POSIX_Asynch_Accept_Handler");
+}
+
+int
+ACE_POSIX_Asynch_Accept_Handler::register_accept_call (ACE_POSIX_Asynch_Accept_Result* result)
+{
+ // The queue is updated by main thread in the register function call
+ // and thru the auxillary thread in the deregister fun. So let us
+ // mutex it.
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ // Insert this result to the queue.
+ int insert_result = this->result_queue_.enqueue_tail (result);
+ if (insert_result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:ACE_POSIX_Asynch_Accept_Handler::register_accept_call failed\n"),
+ -1);
+
+ // If this is the only item, then it means there the set was empty
+ // before. So enable the <handle> in the reactor.
+ if (this->result_queue_.size () == 1)
+ {
+ int return_val = this->reactor_->resume_handler (result->listen_handle ());
+ if (return_val == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:ACE_POSIX_Asynch_Accept_Handler::register_accept_call: "
+ "Reactor::resume_handler failed\n"),
+ -1);
+ }
+
+ return 0;
+}
+
+// @@ We could have a queue where the <result> objects are arranged
+// according to the priority. This will help us to demux the accept
+// completions based on the priority. (Alex).
+
+ACE_POSIX_Asynch_Accept_Result *
+ACE_POSIX_Asynch_Accept_Handler::deregister_accept_call (void)
+{
+ // The queue is updated by main thread in the register function call and
+ // thru the auxillary thread in the deregister fun. So let us mutex
+ // it.
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
+
+ // Get the first item (result ptr) from the Queue.
+ ACE_POSIX_Asynch_Accept_Result* result = 0;
+ if (this->result_queue_.dequeue_head (result) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):%p\n",
+ "ACE_POSIX_Asynch_Accept_Handler::"
+ "deregister_accept_call:dequeueing failed"),
+ 0);
+
+ // ACE_ASSERT (result != 0);
+
+ // Disable the <handle> in the reactor if no <accept>'s are pending.
+ if (this->result_queue_.size () == 0)
+ {
+ if (this->reactor_->suspend_handler (result->listen_handle ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):%p\n",
+ "ACE_POSIX_Asynch_Accept_Handler::"
+ "deregister_accept_call:suspend handler failed"),
+ 0);
+ }
+
+ // Return the result pointer.
+ return result;
+}
+
+
+//@@ New method cancel_uncompleted
+// It performs cancellation of all pending requests
+//
+// Parameter flg_notify can be
+// 0 - don't send notifications about canceled accepts
+// !0 - notify user about canceled accepts
+// according POSIX standards we should receive notifications
+// on canceled AIO requests
+//
+// Return value : number of cancelled requests
+//
+
+int
+ACE_POSIX_Asynch_Accept_Handler::cancel_uncompleted (int flg_notify)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ int retval = 0;
+
+ for (; ; retval++)
+ {
+ ACE_POSIX_Asynch_Accept_Result* result = 0;
+
+ this->result_queue_.dequeue_head (result);
+
+ if (result == 0)
+ break;
+
+ this->reactor_->suspend_handler (result->listen_handle ());
+
+ if (! flg_notify) //if we should not notify
+ delete result ; // we have to delete result
+ else //else notify as any cancelled AIO
+ {
+ // Store the new handle.
+ result->aio_fildes = ACE_INVALID_HANDLE ;
+ result->set_bytes_transferred (0);
+ result->set_error (ECANCELED);
+
+ if (this->posix_proactor_->post_completion (result) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "ACE_POSIX_Asynch_Accept_Handler::"
+ "cancel_uncompleted:<post_completion> failed"));
+ }
+ }
+
+ return retval;
+}
+
+
+int
+ACE_POSIX_Asynch_Accept_Handler::handle_input (ACE_HANDLE /* fd */)
+{
+ // An <accept> has been sensed on the <listen_handle>. We should be
+ // able to just go ahead and do the <accept> now on this <fd>. This
+ // should be the same as the <listen_handle>.
+
+ // Deregister this info pertaining to this <accept> call.
+ ACE_POSIX_Asynch_Accept_Result* result = this->deregister_accept_call ();
+ if (result == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):%p\n",
+ "ACE_POSIX_AIOCB_Asynch_Accept_Handler::"
+ "handle_input:deregister_accept_call failed"),
+ -1);
+
+ // Issue <accept> now.
+ // @@ We shouldnt block here since we have already done poll/select
+ // thru reactor. But are we sure?
+ ACE_HANDLE new_handle = ACE_OS::accept (result->listen_handle (), 0, 0);
+ if (new_handle == ACE_INVALID_HANDLE)
+ {
+ result->set_error(errno);
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t):%p\n",
+ "ACE_POSIX_AIOCB_Asynch_Accept_Handler::"
+ "handle_input:<accept> system call failed"));
+
+ // Notify client as usual, "AIO" finished with errors
+ }
+
+ // Store the new handle.
+ result->aio_fildes = new_handle;
+
+ // Notify the main process about this completion
+ // Send the Result through the notification pipe.
+ if (this->posix_proactor_->post_completion (result) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "ACE_POSIX_AIOCB_Asynch_Accept_Handler::"
+ "handle_input:<post_completion> failed"),
+ -1);
+
+ return 0;
+}
+
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Accept::ACE_POSIX_Asynch_Accept (ACE_POSIX_Proactor *posix_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Accept_Impl (),
+ ACE_POSIX_Asynch_Operation (),
+ accept_handler_ (0),
+ grp_id_(-1), //thread not spawn
+ posix_proactor_ (posix_proactor) //save concrete proactor impl.
+{
+}
+
+int
+ACE_POSIX_Asynch_Accept::accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ // Sanity check: make sure that enough space has been allocated by
+ // the caller.
+ size_t address_size = sizeof (sockaddr_in) + sizeof (sockaddr);
+ size_t space_in_use = message_block.wr_ptr () - message_block.base ();
+ size_t total_size = message_block.size ();
+ size_t available_space = total_size - space_in_use;
+ size_t space_needed = bytes_to_read + 2 * address_size;
+ if (available_space < space_needed)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("Buffer too small\n")), -1);
+
+ // Common code for both WIN and POSIX.
+ ACE_POSIX_Asynch_Accept_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Accept_Result (*this->handler_,
+ this->handle_,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ this->posix_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Register this <accept> call with the local handler.
+ if (this->accept_handler_->register_accept_call (result) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+ACE_POSIX_Asynch_Accept::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ // check for non zero accept_handler_
+ // we could not create a new handler without closing the previous
+
+ if (this->accept_handler_ != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:ACE_POSIX_Asynch_Accept::open:"
+ "accept_handler_ not null\n"),
+ -1);
+
+
+ int result = ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+ if (result == -1)
+ return result;
+
+ // Init the Asynch_Accept_Handler now. It needs to keep Proactor
+ // also with it.
+ ACE_NEW_RETURN (this->accept_handler_,
+ ACE_POSIX_Asynch_Accept_Handler (&this->reactor_,
+ this->posix_proactor_),
+ -1);
+
+ // Register the handle with the reactor.
+ int return_val = this->reactor_.register_handler (this->handle_,
+ this->accept_handler_,
+ ACE_Event_Handler::ACCEPT_MASK);
+ if (return_val == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:Reactor::register_handler failed\n"),
+ -1);
+
+ // Suspend the <handle> now. Enable only when the <accept> is issued
+ // by the application.
+ return_val = this->reactor_.suspend_handler (this->handle_);
+ if (return_val == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:Reactor::suspend_handler failed\n"),
+ -1);
+
+ // Spawn the thread. It is the only thread we are going to have. It
+ // will do the <handle_events> on the reactor.
+ // save group id of the created thread
+
+ grp_id_ = ACE_Thread_Manager::instance ()->spawn (ACE_POSIX_Asynch_Accept::thread_function,
+ ACE_reinterpret_cast (void *, &this->reactor_));
+ if (grp_id_ == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:Thread_Manager::spawn failed\n"),
+ -1);
+
+ return 0;
+}
+
+ACE_POSIX_Asynch_Accept::~ACE_POSIX_Asynch_Accept (void)
+{
+ this->close (0); // not send notifications to user
+}
+
+int
+ACE_POSIX_Asynch_Accept::close (int flg_notify)
+{
+ // 1. It performs cancellation of all pending requests
+ // 2. Stops and waits for the thread we had created
+ // 3. Removes accept_handler_ from Reactor
+ // 4. Deletes accept_handler_
+ // 5. close the socket
+ //
+ // Parameter flg_notify can be
+ // 0 - don't send notifications about canceled accepts
+ // !0 - notify user about canceled accepts
+ // according POSIX standards we should receive notifications
+ // on canceled AIO requests
+ //
+ // Return codes : 0 - OK ,
+ // -1 - Errors
+
+ if (this->accept_handler_)
+ this->accept_handler_->cancel_uncompleted (flg_notify);
+
+ //stop and wait for the thread
+
+ if (grp_id_ != -1)
+ {
+ reactor_.end_reactor_event_loop ();
+
+ if (ACE_Thread_Manager::instance ()->wait_grp (grp_id_) ==-1)
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:Thread_Manager::wait_grp failed\n"));
+ else
+ grp_id_ = -1;
+ }
+
+ //AL remove and destroy accept_handler_
+
+ if (this->accept_handler_ != 0)
+ {
+ this->reactor_.remove_handler
+ (this->accept_handler_,
+ ACE_Event_Handler::ALL_EVENTS_MASK
+ | ACE_Event_Handler::DONT_CALL);
+
+ delete this->accept_handler_ ;
+ this->accept_handler_ = 0 ;
+ }
+
+ // It looks like a good place to close listen handle here.
+ // But I am not sure with compatibility with the old programs
+ // You can comment the closure of the socket
+
+ if (this->handle_ != ACE_INVALID_HANDLE)
+ {
+ ACE_OS::closesocket (this->handle_);
+ this->handle_=ACE_INVALID_HANDLE;
+ }
+
+ return 0;
+}
+
+void *
+ACE_POSIX_Asynch_Accept::thread_function (void *arg_reactor)
+{
+ // Retrieve the reactor pointer from the argument.
+ ACE_Reactor *reactor = ACE_reinterpret_cast (ACE_Reactor *,
+ arg_reactor);
+
+ // It should be valid Reactor, since we have a reactor_ ,e,ner we
+ // are passing only that one here.
+ if (reactor == 0)
+ ACE_ERROR ((LM_ERROR,
+ "%n:%l:Invalid Reactor pointer passed to the thread_function\n",
+ 0));
+
+ // For this reactor, this thread is the owner.
+ reactor->owner (ACE_OS::thr_self ());
+
+ sigset_t RT_signals;
+
+ if (sigemptyset ( & RT_signals ) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "sigemptyset failed"));
+
+ int member = 0;
+
+ for (int si = ACE_SIGRTMIN; si <= ACE_SIGRTMAX; si++)
+ {
+ member = sigismember (& RT_signals , si);
+ if (member == 1)
+ {
+ sigaddset (& RT_signals, si);
+ }
+ }
+
+ if (ACE_OS::pthread_sigmask ( SIG_BLOCK, & RT_signals, 0) != 0)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "pthread_sigmask failed"));
+
+ while (reactor->reactor_event_loop_done () == 0)
+ if (reactor->handle_events () == -1)
+ return ACE_reinterpret_cast (void *, -1);
+
+ return 0;
+}
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route
+// the call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_Asynch_Accept::cancel (void)
+{
+ //We are not ACE_POSIX_Asynch_Operation
+ //so we could not call ::aiocancel ()
+ //We delegate real cancelation to the accept_handler_
+ // accept_handler_->cancel_uncompleted (1)
+
+ //return ACE_POSIX_Asynch_Operation::cancel ();
+
+ if (this->accept_handler_ == 0)
+ return 1 ; // AIO_ALLDONE
+
+ //cancel with notifications as POSIX should do
+
+ int retval = this->accept_handler_->cancel_uncompleted (1);
+
+ //retval contains now the number of canceled requests
+
+ if (retval == 0)
+ return 1 ; // AIO_ALLDONE
+
+ if (retval > 0)
+ return 0; // AIO_CANCELED
+
+ return -1;
+}
+
+ACE_Proactor *
+ACE_POSIX_Asynch_Accept::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// *********************************************************************
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Transmit_File_Result::socket (void) const
+{
+ return this->socket_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Transmit_File_Result::file (void) const
+{
+ return this->aio_fildes;
+}
+
+ACE_Asynch_Transmit_File::Header_And_Trailer *
+ACE_POSIX_Asynch_Transmit_File_Result::header_and_trailer (void) const
+{
+ return this->header_and_trailer_;
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::bytes_to_write (void) const
+{
+ return this->aio_nbytes;
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::bytes_per_send (void) const
+{
+ return this->bytes_per_send_;
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_POSIX_Asynch_Transmit_File_Result::ACE_POSIX_Asynch_Transmit_File_Result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Transmit_File_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, offset, offset_high, priority, signal_number),
+ socket_ (socket),
+ header_and_trailer_ (header_and_trailer),
+ bytes_per_send_ (bytes_per_send),
+ flags_ (flags)
+{
+ this->aio_fildes = file;
+ this->aio_nbytes = bytes_to_write;
+}
+
+void
+ACE_POSIX_Asynch_Transmit_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // We will not do this because (a) the header and trailer blocks may
+ // be the same message_blocks and (b) in cases of failures we have
+ // no idea how much of what (header, data, trailer) was sent.
+ /*
+ if (this->success_ && this->header_and_trailer_ != 0)
+ {
+ ACE_Message_Block *header = this->header_and_trailer_->header ();
+ if (header != 0)
+ header->rd_ptr (this->header_and_trailer_->header_bytes ());
+
+ ACE_Message_Block *trailer = this->header_and_trailer_->trailer ();
+ if (trailer != 0)
+ trailer->rd_ptr (this->header_and_trailer_->trailer_bytes ());
+ }
+ */
+
+ // Create the interface result class.
+ ACE_Asynch_Transmit_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_transmit_file (result);
+}
+
+ACE_POSIX_Asynch_Transmit_File_Result::~ACE_POSIX_Asynch_Transmit_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Transmit_File_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Transmit_File_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Transmit_File_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Transmit_File_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Transmit_File_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Transmit_File_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Transmit_File_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+int
+ACE_POSIX_Asynch_Transmit_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+// *********************************************************************
+
+class ACE_Export ACE_POSIX_Asynch_Transmit_Handler : public ACE_Handler
+{
+ // = TITLE
+ //
+ // Auxillary handler for doing <Asynch_Transmit_File> in
+ // Unix. <ACE_POSIX_Asynch_Transmit_File> internally uses this.
+ //
+ // = DESCRIPTION
+ //
+ // This is a helper class for implementing
+ // <ACE_POSIX_Asynch_Transmit_File> in Unix systems. This class
+ // abstracts out all the commonalities in the two different
+ // POSIX Transmit Handler implementations.
+
+public:
+ virtual ~ACE_POSIX_Asynch_Transmit_Handler (void);
+ // Destructor.
+
+protected:
+ ACE_POSIX_Asynch_Transmit_Handler (ACE_POSIX_Asynch_Transmit_File_Result *result);
+ // Constructor. Result pointer will have all the information to do
+ // the file transmission (socket, file, application handler, bytes
+ // to write).
+
+ ACE_POSIX_Asynch_Transmit_File_Result *result_;
+ // The asynch result pointer made from the initial transmit file
+ // request.
+
+ ACE_Message_Block *mb_;
+ // Message bloack used to do the transmission.
+
+ enum ACT
+ {
+ HEADER_ACT = 1,
+ DATA_ACT = 2,
+ TRAILER_ACT = 3
+ };
+
+ ACT header_act_;
+ ACT data_act_;
+ ACT trailer_act_;
+ // ACT to transmit header, data and trailer.
+
+ size_t file_offset_;
+ // Current offset of the file being transmitted.
+
+ size_t file_size_;
+ // Total size of the file.
+
+ size_t bytes_transferred_;
+ // Number of bytes transferred on the stream.
+};
+
+// ************************************************************
+
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Transmit_Handler : public ACE_POSIX_Asynch_Transmit_Handler
+{
+ // = TITLE
+ //
+ // Auxillary handler for doing <Asynch_Transmit_File> in
+ // Unix. <ACE_POSIX_Asynch_Transmit_File> internally uses this.
+ //
+ // = DESCRIPTION
+ //
+ // This is a helper class for implementing
+ // <ACE_POSIX_Asynch_Transmit_File> in Unix systems.
+
+public:
+ ACE_POSIX_AIOCB_Asynch_Transmit_Handler (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor,
+ ACE_POSIX_Asynch_Transmit_File_Result *result);
+ // Constructor. Result pointer will have all the information to do
+ // the file transmission (socket, file, application handler, bytes
+ // to write).
+
+ virtual ~ACE_POSIX_AIOCB_Asynch_Transmit_Handler (void);
+ // Destructor.
+
+ int transmit (void);
+ // Do the transmission. All the info to do the transmission is in
+ // the <result> member.
+
+protected:
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+ // This is called when asynchronous writes from the socket complete.
+
+ virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
+ // This is called when asynchronous reads from the file complete.
+
+ int initiate_read_file (void);
+ // Issue asynch read from the file.
+
+ ACE_POSIX_AIOCB_Asynch_Read_File rf_;
+ // To read from the file to be transmitted.
+
+ ACE_POSIX_AIOCB_Asynch_Write_Stream ws_;
+ // Write stream to write the header, trailer and the data.
+};
+
+// *********************************************************************
+
+// Constructor.
+ACE_POSIX_Asynch_Transmit_Handler::ACE_POSIX_Asynch_Transmit_Handler (ACE_POSIX_Asynch_Transmit_File_Result *result)
+ : result_ (result),
+ mb_ (0),
+ header_act_ (this->HEADER_ACT),
+ data_act_ (this->DATA_ACT),
+ trailer_act_ (this->TRAILER_ACT),
+ file_offset_ (result->offset ()),
+ file_size_ (0),
+ bytes_transferred_ (0)
+{
+ // Allocate memory for the message block.
+ ACE_NEW (this->mb_,
+ ACE_Message_Block (this->result_->bytes_per_send ()
+ + 1));
+ // Init the file size.
+ file_size_ = ACE_OS::filesize (this->result_->file ());
+}
+
+// Destructor.
+ACE_POSIX_Asynch_Transmit_Handler::~ACE_POSIX_Asynch_Transmit_Handler (void)
+{
+ delete result_;
+ mb_->release ();
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::ACE_POSIX_AIOCB_Asynch_Transmit_Handler (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor,
+ ACE_POSIX_Asynch_Transmit_File_Result *result)
+ : ACE_POSIX_Asynch_Transmit_Handler (result),
+ rf_ (posix_aiocb_proactor),
+ ws_ (posix_aiocb_proactor)
+{
+}
+
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::~ACE_POSIX_AIOCB_Asynch_Transmit_Handler (void)
+{
+}
+
+// Do the transmission.
+// Initiate transmitting the header. When that completes
+// handle_write_stream will be called, there start transmitting the file.
+int
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::transmit (void)
+{
+ // No proactor is given for the <open>'s. Because we are using the
+ // concrete implementations of the Asynch_Operations, and we have
+ // already given them the specific proactor, so they wont need the
+ // general <proactor> interface pointer.
+
+ // Open Asynch_Read_File.
+ if (this->rf_.open (*this,
+ this->result_->file (),
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Asynch_Transmit_Handler:read_file open failed\n"),
+ -1);
+
+ // Open Asynch_Write_Stream.
+ if (this->ws_.open (*this,
+ this->result_->socket (),
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Asynch_Transmit_Handler:write_stream open failed\n"),
+ -1);
+
+ // Transmit the header.
+ if (this->ws_.write (*this->result_->header_and_trailer ()->header (),
+ this->result_->header_and_trailer ()->header_bytes (),
+ ACE_reinterpret_cast (void *, &this->header_act_),
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Asynch_Transmit_Handler:transmitting header:write_stream failed\n"),
+ -1);
+ return 0;
+}
+
+void
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
+{
+ // Update bytes transferred so far.
+ this->bytes_transferred_ += result.bytes_transferred ();
+
+ // Check the success parameter.
+ if (result.success () == 0)
+ {
+ // Failure.
+ ACE_ERROR ((LM_ERROR,
+ "Asynch_Transmit_File failed.\n"));
+
+ ACE_SEH_TRY
+ {
+ this->result_->complete (this->bytes_transferred_,
+ 0, // Failure.
+ 0, // @@ Completion key.
+ 0); // @@ Error no.
+ }
+ ACE_SEH_FINALLY
+ {
+ // This is crucial to prevent memory leaks. This deletes
+ // the result pointer also.
+ delete this;
+ }
+ }
+
+ // Write stream successful.
+
+ // Partial write to socket.
+ int unsent_data = result.bytes_to_write () - result.bytes_transferred ();
+ if (unsent_data != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:Partial write to socket: Asynch_write called again\n"));
+
+ // Duplicate the message block and retry remaining data
+ if (this->ws_.write (*result.message_block ().duplicate (),
+ unsent_data,
+ result.act (),
+ this->result_->priority (),
+ this->result_->signal_number ()) == -1)
+ {
+ // @@ Handle this error.
+ ACE_ERROR ((LM_ERROR,
+ "Asynch_Transmit_Handler:write_stream failed\n"));
+ return;
+ }
+
+ // @@ Handling *partial write* to a socket. Let us not continue
+ // further before this write finishes. Because proceeding with
+ // another read and then write might change the order of the
+ // file transmission, because partial write to the stream is
+ // always possible.
+ return;
+ }
+
+ // Not a partial write. A full write.
+
+ // Check ACT to see what was sent.
+ ACT act = * (ACT *) result.act ();
+
+ switch (act)
+ {
+ case TRAILER_ACT:
+ // If it is the "trailer" that is just sent, then transmit file
+ // is complete.
+ // Call the application handler.
+ ACE_SEH_TRY
+ {
+ this->result_->complete (this->bytes_transferred_,
+ 1, // @@ Success.
+ 0, // @@ Completion key.
+ 0); // @@ Errno.
+ }
+ ACE_SEH_FINALLY
+ {
+ delete this;
+ }
+ break;
+
+ case HEADER_ACT:
+ case DATA_ACT:
+ // If header/data was sent, initiate the file data transmission.
+ if (this->initiate_read_file () == -1)
+ // @@ Handle this error.
+ ACE_ERROR ((LM_ERROR,
+ "Error:Asynch_Transmit_Handler:read_file couldnt be initiated\n"));
+ break;
+
+ default:
+ // @@ Handle this error.
+ ACE_ERROR ((LM_ERROR,
+ "Error:ACE_Asynch_Transmit_Handler::handle_write_stream::Unexpected act\n"));
+ }
+}
+
+void
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::handle_read_file (const ACE_Asynch_Read_File::Result &result)
+{
+ // Failure.
+ if (result.success () == 0)
+ {
+ //
+ ACE_SEH_TRY
+ {
+ this->result_->complete (this->bytes_transferred_,
+ 0, // Failure.
+ 0, // @@ Completion key.
+ errno); // Error no.
+ }
+ ACE_SEH_FINALLY
+ {
+ delete this;
+ }
+ return;
+ }
+
+ // Read successful.
+ if (result.bytes_transferred () == 0)
+ return;
+
+ // Increment offset.
+ this->file_offset_ += result.bytes_transferred ();
+
+ // Write data to network.
+ if (this->ws_.write (result.message_block (),
+ result.bytes_transferred (),
+ (void *)&this->data_act_,
+ this->result_->priority (),
+ this->result_->signal_number ()) == -1)
+ {
+ // @@ Handle this error.
+ ACE_ERROR ((LM_ERROR,
+ "Error:ACE_Asynch_Transmit_File : write to the stream failed\n"));
+ return;
+ }
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Transmit_Handler::initiate_read_file (void)
+{
+ // Is there something to read.
+ if (this->file_offset_ >= this->file_size_)
+ {
+ // File is sent. Send the trailer.
+ if (this->ws_.write (*this->result_->header_and_trailer ()->trailer (),
+ this->result_->header_and_trailer ()->trailer_bytes (),
+ (void *)&this->trailer_act_,
+ this->result_->priority (),
+ this->result_->signal_number ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:Asynch_Transmit_Handler:write_stream writing trailer failed\n"),
+ -1);
+ return 0;
+ }
+ else
+ {
+ // @@ Is this right??
+ // Previous reads and writes are over. For the new read, adjust
+ // the wr_ptr and the rd_ptr to the beginning.
+ this->mb_->rd_ptr (this->mb_->base ());
+ this->mb_->wr_ptr (this->mb_->base ());
+
+ // Inititiate an asynchronous read from the file.
+ if (this->rf_.read (*this->mb_,
+ this->mb_->size () - 1,
+ this->file_offset_,
+ 0, // @@ offset_high !!! if aiocb64 is used.
+ 0, // Act
+ this->result_->priority (),
+ this->result_->signal_number ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:Asynch_Transmit_Handler::read from file failed\n"),
+ -1);
+ return 0;
+ }
+}
+
+// *********************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Transmit_File::ACE_POSIX_AIOCB_Asynch_Transmit_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Transmit_File_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Operation (posix_aiocb_proactor)
+{
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ // Adjust these parameters if there are default values specified.
+ ssize_t file_size = ACE_OS::filesize (file);
+
+ if (file_size == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%N:%l:%p\n",
+ "POSIX_AIOCB_Asynch_Transmit_File:filesize failed"),
+ -1);
+
+ if (bytes_to_write == 0)
+ bytes_to_write = file_size;
+
+ if (offset > (size_t) file_size)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%p\n",
+ "Asynch_Transmit_File:File size is less than offset"),
+ -1);
+
+ if (offset != 0)
+ bytes_to_write = file_size - offset + 1;
+
+ if (bytes_per_send == 0)
+ bytes_per_send = bytes_to_write;
+
+ // Configure the result parameter.
+ ACE_POSIX_Asynch_Transmit_File_Result *result = 0;
+
+ ACE_NEW_RETURN (result,
+ ACE_POSIX_Asynch_Transmit_File_Result (*this->handler_,
+ this->handle_,
+ file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ this->posix_proactor ()->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Make the auxillary handler and initiate transmit.
+ ACE_POSIX_AIOCB_Asynch_Transmit_Handler *transmit_handler = 0;
+
+ ACE_NEW_RETURN (transmit_handler,
+ ::ACE_POSIX_AIOCB_Asynch_Transmit_Handler (this->posix_proactor (),
+ result),
+ -1);
+
+ ssize_t return_val = transmit_handler->transmit ();
+
+ if (return_val == -1)
+ // This deletes the <result> in it too.
+ delete transmit_handler;
+
+ return 0;
+}
+
+ACE_POSIX_AIOCB_Asynch_Transmit_File::~ACE_POSIX_AIOCB_Asynch_Transmit_File (void)
+{
+}
+
+
+// Methods belong to ACE_POSIX_Asynch_Operation base class. These
+// methods are defined here to avoid dominance warnings. They route the
+// call to the ACE_POSIX_Asynch_Operation base class.
+
+int
+ACE_POSIX_AIOCB_Asynch_Transmit_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Transmit_File::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Transmit_File::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+// *********************************************************************
+u_long
+ACE_POSIX_Asynch_Read_Dgram_Result::bytes_to_read (void) const
+{
+ return this->bytes_to_read_;
+}
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::remote_address (ACE_Addr& addr) const
+{
+ int retVal = -1; // failure
+
+ // make sure the addresses are of the same type
+ if (addr.get_type () == this->remote_address_->get_type ())
+ { // copy the remote_address_ into addr
+ addr.set_addr (this->remote_address_->get_addr (),
+ this->remote_address_->get_size ());
+ retVal = 0; // success
+ }
+
+ return retVal;
+}
+
+sockaddr *
+ACE_POSIX_Asynch_Read_Dgram_Result::saddr () const
+{
+ return (sockaddr *) this->remote_address_->get_addr ();
+}
+
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_Dgram_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Dgram_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_Dgram_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Read_Dgram_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Dgram_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Read_Dgram_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Dgram_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Read_Dgram_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+int
+ACE_POSIX_Asynch_Read_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+ACE_Message_Block*
+ACE_POSIX_Asynch_Read_Dgram_Result::message_block () const
+{
+ return this->message_block_;
+}
+
+ACE_POSIX_Asynch_Read_Dgram_Result::ACE_POSIX_Asynch_Read_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ u_long bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Dgram_Result_Impl(),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_read_ (bytes_to_read),
+ message_block_ (message_block),
+ remote_address_ (0),
+ addr_len_ (0),
+ flags_ (flags),
+ handle_ (handle)
+{
+ ACE_UNUSED_ARG (protocol_family);
+ this->aio_fildes = handle;
+ this->aio_nbytes = bytes_to_read;
+ ACE_NEW (this->remote_address_, ACE_INET_Addr);
+}
+
+void
+ACE_POSIX_Asynch_Read_Dgram_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <errno> is available in the aiocb.
+ ACE_UNUSED_ARG (error);
+
+ this->remote_address_->set_size(this->addr_len_);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_Dgram::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_dgram (result);
+}
+
+ACE_POSIX_Asynch_Read_Dgram_Result::~ACE_POSIX_Asynch_Read_Dgram_Result (void)
+{
+ delete this->remote_address_;
+}
+
+//***************************************************************************
+u_long
+ACE_POSIX_Asynch_Write_Dgram_Result::bytes_to_write (void) const
+{
+ return this->bytes_to_write_;
+}
+
+int
+ACE_POSIX_Asynch_Write_Dgram_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_Dgram_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Dgram_Result::bytes_transferred (void) const
+{
+ return ACE_POSIX_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_Dgram_Result::act (void) const
+{
+ return ACE_POSIX_Asynch_Result::act ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Dgram_Result::success (void) const
+{
+ return ACE_POSIX_Asynch_Result::success ();
+}
+
+const void *
+ACE_POSIX_Asynch_Write_Dgram_Result::completion_key (void) const
+{
+ return ACE_POSIX_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Dgram_Result::error (void) const
+{
+ return ACE_POSIX_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_POSIX_Asynch_Write_Dgram_Result::event (void) const
+{
+ return ACE_POSIX_Asynch_Result::event ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Dgram_Result::offset (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset ();
+}
+
+u_long
+ACE_POSIX_Asynch_Write_Dgram_Result::offset_high (void) const
+{
+ return ACE_POSIX_Asynch_Result::offset_high ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Dgram_Result::priority (void) const
+{
+ return ACE_POSIX_Asynch_Result::priority ();
+}
+
+int
+ACE_POSIX_Asynch_Write_Dgram_Result::signal_number (void) const
+{
+ return ACE_POSIX_Asynch_Result::signal_number ();
+}
+
+ACE_Message_Block*
+ACE_POSIX_Asynch_Write_Dgram_Result::message_block () const
+{
+ return this->message_block_;
+}
+
+
+int
+ACE_POSIX_Asynch_Write_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_POSIX_Asynch_Result::post_completion (proactor);
+}
+
+ACE_POSIX_Asynch_Write_Dgram_Result::ACE_POSIX_Asynch_Write_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Dgram_Result_Impl(),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_write_ (bytes_to_write),
+ message_block_ (message_block),
+ flags_ (flags),
+ handle_ (handle)
+
+{
+ this->aio_fildes = handle;
+ this->aio_nbytes = bytes_to_write;
+
+}
+
+void
+ACE_POSIX_Asynch_Write_Dgram_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // <errno> is available in the aiocb.
+ ACE_UNUSED_ARG (error);
+
+ // Appropriately move the pointers in the message block.
+ //this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Dgram::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_dgram (result);
+}
+
+ACE_POSIX_Asynch_Write_Dgram_Result::~ACE_POSIX_Asynch_Write_Dgram_Result (void)
+{
+}
+
+/***************************************************************************/
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::~ACE_POSIX_AIOCB_Asynch_Read_Dgram (void)
+{
+}
+
+ssize_t
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_UNUSED_ARG (message_block);
+ ACE_UNUSED_ARG (number_of_bytes_recvd);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (protocol_family);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_AIOCB_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::cancel (void)
+{
+ return ACE_POSIX_AIOCB_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::proactor (void) const
+{
+ return ACE_POSIX_AIOCB_Asynch_Operation::proactor ();
+}
+
+ACE_POSIX_AIOCB_Asynch_Read_Dgram::ACE_POSIX_AIOCB_Asynch_Read_Dgram (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Dgram_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Operation (posix_aiocb_proactor)
+{
+}
+//***************************************************************************
+
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::~ACE_POSIX_AIOCB_Asynch_Write_Dgram (void)
+{
+}
+
+ssize_t
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_UNUSED_ARG (message_block);
+ ACE_UNUSED_ARG (number_of_bytes_sent);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_POSIX_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::cancel (void)
+{
+ return ACE_POSIX_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::proactor (void) const
+{
+ return ACE_POSIX_Asynch_Operation::proactor ();
+}
+
+ACE_POSIX_AIOCB_Asynch_Write_Dgram::ACE_POSIX_AIOCB_Asynch_Write_Dgram (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Dgram_Impl (),
+ ACE_POSIX_AIOCB_Asynch_Operation (posix_aiocb_proactor)
+{
+}
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Unbounded_Queue<ACE_POSIX_Asynch_Accept_Result *>;
+template class ACE_Node<ACE_POSIX_Asynch_Accept_Result *>;
+template class ACE_Unbounded_Queue_Iterator<ACE_POSIX_Asynch_Accept_Result *>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Unbounded_Queue<ACE_POSIX_Asynch_Accept_Result *>
+#pragma instantiate ACE_Node<ACE_POSIX_Asynch_Accept_Result *>
+#pragma instantiate ACE_Unbounded_Queue_Iterator<ACE_POSIX_Asynch_Accept_Result *>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+#endif /* ACE_HAS_AIO_CALLS */
diff --git a/ace/Connection/POSIX_Asynch_IO.h b/ace/Connection/POSIX_Asynch_IO.h
new file mode 100644
index 00000000000..7f9693ab963
--- /dev/null
+++ b/ace/Connection/POSIX_Asynch_IO.h
@@ -0,0 +1,1732 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file POSIX_Asynch_IO.h
+ *
+ * $Id$
+ *
+ * The implementation classes for POSIX implementation of Asynch
+ * Operations are defined here in this file.
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ * @author Alexander Libman <alibman@baltimore.com>
+ */
+//=============================================================================
+
+#ifndef ACE_POSIX_ASYNCH_IO_H
+#define ACE_POSIX_ASYNCH_IO_H
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Reactor.h"
+
+// Forward declarations
+class ACE_POSIX_SIG_Proactor;
+class ACE_POSIX_AIOCB_Proactor;
+class ACE_Proactor_Impl;
+
+/**
+ * @class ACE_POSIX_Asynch_Result
+ *
+ * This class provides concrete implementation for <ACE_Asynch_Result>
+ * for POSIX4 platforms. This class extends <aiocb> and makes it more
+ * useful.
+ */
+class ACE_Export ACE_POSIX_Asynch_Result : public virtual ACE_Asynch_Result_Impl,
+ public aiocb
+{
+public:
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE on POSIX4 platforms.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// Priority of the operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls.
+ */
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Result (void);
+
+ /// Simulate error value to use in the post_completion ()
+ void set_error (u_long errcode);
+
+ /// Simulate value to use in the post_completion ()
+ void set_bytes_transferred (u_long nbytes);
+
+protected:
+ /// Constructor. <Event> is not used on POSIX.
+ ACE_POSIX_Asynch_Result (ACE_Handler &handler,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number);
+
+ /// Handler that will be called back.
+ ACE_Handler &handler_;
+
+ /**
+ * ACT for this operation.
+ * We could use <aiocb::aio_sigevent.sigev_value.sival_ptr> for
+ * this. But it doesnot provide the constness, so this may be
+ * better.
+ */
+ const void *act_;
+
+ /// Bytes transferred by this operation.
+ u_long bytes_transferred_;
+
+ /// Success indicator.
+ int success_;
+
+ /// ACT associated with handle.
+ const void *completion_key_;
+
+ /// Error if operation failed.
+ u_long error_;
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Operation
+ *
+ * @brief This class abstracts out the common things needed for
+ * implementing <Asynch_Operation> for POSIX platforms. Specific
+ * implementations such as <POSIX_AIOCB_Asynch_Operation>
+ * can derive from this class.
+ */
+class ACE_Export ACE_POSIX_Asynch_Operation : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle. No need for the Proactor since the sub classes
+ * will know the correct implementation Proactor class, since this
+ * Operation class itself was created by the correct implementation
+ * Proactor class.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ /// Check the documentation for <ACE_Asynch_Operation::cancel>.
+ int cancel (void);
+
+ // = Access methods.
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// No op contructor.
+ ACE_POSIX_Asynch_Operation (void);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Operation (void);
+
+ /// Proactor that this Asynch IO will be registered with.
+ ACE_Proactor *proactor_;
+
+ /// Handler that will receive the callback.
+ ACE_Handler *handler_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Operation
+ *
+ * @brief This class implements <ACE_Asynch_Operation> for <AIOCB>
+ * (Asynchronous I/O Control Blocks) based implementation of
+ * Proactor.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Operation : public virtual ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Return the underlying Proactor implementation.
+ ACE_POSIX_AIOCB_Proactor *posix_proactor (void) const;
+
+protected:
+ /// Contructor.
+ ACE_POSIX_AIOCB_Asynch_Operation (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Operation (void);
+
+ /// This is the method which does the real work to start aio
+ /// and should be used instead of shared_read/shared_write
+ /// <op> means operation : 0 - read , 1 - write.
+ virtual int register_and_start_aio (ACE_POSIX_Asynch_Result *result,
+ int op);
+
+ // This call is for the POSIX implementation. This method is used by
+ // <ACE_Asynch_Operation> to store some information with the
+ // Proactor after an <aio_> call is issued, so that the Proactor can
+ // retreve this information to do <aio_return> and <aio_error>.
+ // Passing a '0' ptr returns the status, indicating whether there
+ // are slots available or no. Passing a valid ptr stores the ptr
+ // with the Proactor.
+
+ /**
+ * It is easy to get this specific implementation proactor here,
+ * since it is the one that creates the correct POSIX_Asynch_*
+ * objects. We can use this to get to the implementation proactor
+ * directly.
+ */
+ ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_;
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Read_Stream_Result
+ *
+ * @brief This class provides concrete implementation for
+ * <ACE_Asynch_Read_Stream::Result> class for POSIX platforms.
+ */
+class ACE_Export ACE_POSIX_Asynch_Read_Stream_Result : public virtual ACE_Asynch_Read_Stream_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+
+ /// Factory classes willl have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Read_Stream;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ // = Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Read_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_Stream factory.
+
+ /// Get the data copied to this class, before calling application
+ /// handler.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destrcutor.
+ virtual ~ACE_POSIX_Asynch_Read_Stream_Result (void);
+
+ // aiocb::aio_nbytes
+ // Bytes requested when the asynchronous read was initiated.
+
+ /// Message block for reading the data into.
+ ACE_Message_Block &message_block_;
+
+ // aiocb::aio_filedes
+ // I/O handle used for reading.
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Read_Stream
+ *
+ * This class implements <ACE_Asynch_Read_Stream> for <AIOCB>
+ * (Asynchronous I/O Control Blocks) based implementation of Proactor.
+ *
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Read_Stream : public virtual ACE_Asynch_Read_Stream_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Read_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /// This starts off an asynchronous read. Upto <bytes_to_read> will
+ /// be read and stored in the <message_block>.
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Read_Stream (void);
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ ///
+ /// @@ Not implemented. Returns 0.
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+};
+
+
+/**
+ * @class ACE_POSIX_Asynch_Write_Stream_Result
+ *
+ * @brief This class provides concrete implementation for
+ * <ACE_Asynch_Write_Stream::Result> on POSIX platforms.
+ *
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ */
+class ACE_Export ACE_POSIX_Asynch_Write_Stream_Result : public virtual ACE_Asynch_Write_Stream_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+ /// Factory classes will have special privilages.
+ friend class ACE_POSIX_AIOCB_Asynch_Write_Stream;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ // = Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE on POSIX4 platforms.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Write_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_Stream factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_Stream_Result (void);
+
+protected:
+ // aiocb::aio_nbytes
+ // The number of bytes which were requested at the start of the
+ // asynchronous write.
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block_;
+
+ // aiocb::aio_filedes
+ // I/O handle used for writing.
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Write_Stream
+ *
+ * @brief This class implements <ACE_Asynch_Write_Stream> for <AIOCB>
+ * (Asynchronous I/O Control Blocks) based implementation of
+ * Proactor.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Write_Stream : public virtual ACE_Asynch_Write_Stream_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Write_Stream (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /// This starts off an asynchronous write. Upto <bytes_to_write>
+ /// will be written from the <message_block>.
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Write_Stream (void);
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ ///
+ /// @@ Not implemented. Returns 0.
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Read_File_Result
+ *
+ * @brief This class provides concrete implementation for
+ * <ACE_Asynch_Read_File::Result> class for POSIX platforms.
+ */
+class ACE_Export ACE_POSIX_Asynch_Read_File_Result : public virtual ACE_Asynch_Read_File_Result_Impl,
+ public ACE_POSIX_Asynch_Read_Stream_Result
+{
+ /// Factory classes willl have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Read_File;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ // = These methods belong to ACE_POSIX_Asynch_Result class base
+ // class. These operations are here to kill dominance
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE on POSIX4 platforms.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ // = The following methods belong to
+ // ACE_POSIX_Asynch_Read_Stream_Result. They are here to avoid
+ // dominance warnings. These methods route their call to the
+ // ACE_POSIX_Asynch_Read_Stream_Result base class.
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Read_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_File factory.
+
+ /// ACE_Proactor will call this method when the read completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Read_File_Result (void);
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Read_File
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a file. This class implements <ACE_Asynch_Read_File> for
+ * <AIOCB> (Asynchronous I/O Control Blocks) based implementation
+ * of Proactor.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can
+ * started using this class. A <ACE_Asynch_Read_File::Result>
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_file>
+ * callback.
+ *
+ * This class differs slightly from <ACE_Asynch_Read_Stream> as it
+ * allows the user to specify an offset for the read.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Read_File : public virtual ACE_Asynch_Read_File_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Read_Stream
+{
+
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Read_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /**
+ * This starts off an asynchronous read. Upto <bytes_to_read> will
+ * be read and stored in the <message_block>. The read will start
+ * at <offset> from the beginning of the file.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Read_File (void);
+
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ ///
+ /// @@ Not implemented. Returns 0.
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ /**
+ * This belongs to ACE_POSIX_AIOCB_Asynch_Read_Stream. We have
+ * defined this here to avoid compiler warnings and forward the
+ * method to <ACE_POSIX_AIOCB_Asynch_Read_Stream::read>.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+};
+
+
+/**
+ * @class ACE_POSIX_Asynch_Write_File_Result
+ *
+ * @brief This class provides implementation for
+ * <ACE_Asynch_Write_File_Result> for POSIX platforms.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ *
+ * This class differs slightly from
+ * <ACE_Asynch_Write_Stream::Result> as it calls back
+ * <ACE_Handler::handle_write_file> on the <handler> instead of
+ * <ACE_Handler::handle_write_stream>. No additional state is
+ * required by this class as <ACE_Asynch_Result> can store the
+ * <offset>.
+ */
+class ACE_Export ACE_POSIX_Asynch_Write_File_Result : public virtual ACE_Asynch_Write_File_Result_Impl,
+ public ACE_POSIX_Asynch_Write_Stream_Result
+{
+ /// Factory classes will have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Write_File;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE on POSIX4 platforms.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ // = The following methods belong to
+ // ACE_POSIX_Asynch_Write_Stream_Result. They are here to avoid
+ // dominace warnings. These methods route their call to the
+ // ACE_POSIX_Asynch_Write_Stream_Result base class.
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Write_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_File factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_File_Result (void);
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Write_File
+ *
+ * This class provides concrete implementation for
+ * <ACE_Asynch_Write_File> for POSIX platforms where the
+ * completion strategy for Proactor is based on AIOCB (AIO
+ * Control Blocks).
+ *
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Write_File : public virtual ACE_Asynch_Write_File_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Write_Stream
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Write_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /**
+ * This starts off an asynchronous write. Upto <bytes_to_write>
+ * will be written and stored in the <message_block>. The write will
+ * start at <offset> from the beginning of the file.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Write_File (void);
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ ///
+ /// @@ Not implemented. Returns 0.
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ /**
+ * This <write> belongs to ACE_POSIX_AIOCB_Asynch_Write_Stream. We
+ * have put this here to avoid compiler warnings. We forward this
+ * method call to the <ACE_POSIX_AIOCB_Asynch_Write_Stream::write>
+ * one.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Accept_Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous accept completes.
+ *
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous accept.
+ */
+class ACE_Export ACE_POSIX_Asynch_Accept_Result : public virtual ACE_Asynch_Accept_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+ /// Factory classes willl have special permissions.
+ friend class ACE_POSIX_Asynch_Accept;
+ friend class ACE_POSIX_Asynch_Accept_Handler;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous accept.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for accepting new connections.
+ ACE_HANDLE listen_handle (void) const;
+
+ /// I/O handle for the new connection.
+ ACE_HANDLE accept_handle (void) const;
+
+ // = Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE on POSIX4 platforms.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Accept_Result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Accept factory.
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Accept_Result (void);
+
+ // aiocb::aio_nbytes
+ // Bytes requested when the asynchronous read was initiated.
+ // Actually, on POSIX implementation, we dont read any intial data.
+
+ /// Message block for reading the data into.
+ ACE_Message_Block &message_block_;
+
+ /// I/O handle used for accepting new connections.
+ ACE_HANDLE listen_handle_;
+
+ // aiocb::aio_filedes
+ // I/O handle for the new connection.
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Accept_Handler
+ *
+ * Forward declaration. This class is defined the in the cpp file,
+ * since this is internal to the implementation.
+ */
+class ACE_POSIX_Asynch_Accept_Handler;
+
+/**
+ * @class ACE_POSIX_Asynch_Accept
+ *
+ */
+class ACE_Export ACE_POSIX_Asynch_Accept :
+ public virtual ACE_Asynch_Accept_Impl,
+ public ACE_POSIX_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_Asynch_Accept (ACE_POSIX_Proactor * posix_proactor);
+
+ /**
+ * This <open> belongs to ACE_AIOCB_Asynch_Operation. We forward
+ * this call to that method. We have put this here to avoid the
+ * compiler warnings.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ /**
+ * This starts off an asynchronous accept. The asynchronous accept
+ * call also allows any initial data to be returned to the
+ * <handler>. Upto <bytes_to_read> will be read and stored in the
+ * <message_block>. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * <message_block> must be specified. This is because the address of
+ * the new connection is placed at the end of this buffer.
+ */
+ int accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Accept (void);
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Cancel all pending pseudo-asynchronus requests
+ * Behavior as usual AIO request
+ */
+ int cancel (void);
+
+ /**
+ * Close performs cancellation of all pending requests
+ * Parameter flg_notify can be
+ * 0 - don't send notifications about canceled accepts
+ * 1 - notify user about canceled accepts
+ * according POSIX standards we should receive notifications
+ * on canceled AIO requests
+ */
+ int close ( int flg_notify);
+
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ /// The thread function that does handle events.
+ static void* thread_function (void* reactor);
+
+ /// Reactor to wait on the <listen_handle>.
+ ACE_Reactor reactor_;
+
+ /// The Event Handler to do handle_input.
+ ACE_POSIX_Asynch_Accept_Handler* accept_handler_;
+
+ /// group id for the thread that we create for accepts
+ int grp_id_ ;
+
+ /// POSIX Proactor implementation
+ ACE_POSIX_Proactor * posix_proactor_;
+};
+
+
+/**
+ * @class ACE_POSIX_Asynch_Transmit_File_Result
+ *
+ * @brief This is that class which will be passed back to the
+ * <handler> when the asynchronous transmit file completes.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous transmit file.
+ */
+class ACE_Export ACE_POSIX_Asynch_Transmit_File_Result : public virtual ACE_Asynch_Transmit_File_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+ /// Factory classes willl have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Transmit_File;
+
+ /// Handlers do all the job.
+ friend class ACE_POSIX_Asynch_Transmit_Handler;
+ friend class ACE_POSIX_AIOCB_Asynch_Transmit_Handler;
+
+ /// The Proactor constructs the Result class for faking results.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// Socket used for transmitting the file.
+ ACE_HANDLE socket (void) const;
+
+ /// File from which the data is read.
+ ACE_HANDLE file (void) const;
+
+ /// Header and trailer data associated with this transmit file.
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer (void) const;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous transmit file.
+ u_long bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ u_long bytes_per_send (void) const;
+
+ /// Flags which were passed into transmit file.
+ u_long flags (void) const;
+
+ // = Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This is the ACT associated with the handle on which the
+ * Asynch_Operation takes place.
+ *
+ * @@ This is not implemented for POSIX4 platforms.
+ *
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// This returns ACE_INVALID_HANDLE.
+ ACE_HANDLE event (void) const;
+
+ /**
+ * This really make sense only when doing file I/O.
+ *
+ * @@ On POSIX4-Unix, offset_high should be supported using
+ * aiocb64.
+ *
+ */
+ u_long offset (void) const;
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation.
+ int priority (void) const;
+
+ /**
+ * POSIX4 realtime signal number to be used for the
+ * operation. <signal_number> ranges from SIGRTMIN to SIGRTMAX. By
+ * default, SIGRTMIN is used to issue <aio_> calls. This is a no-op
+ * on non-POSIX4 systems and returns 0.
+ */
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Transmit_File_Result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Transmit_File factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Transmit_File_Result (void);
+
+ /// Network I/O handle.
+ ACE_HANDLE socket_;
+
+ // aiocb::aio_filedes
+ // File I/O handle.
+
+ /// Header and trailer data associated with this transmit file.
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer_;
+
+ // aiocb::aio_nbytes
+ // The number of bytes which were requested at the start of the
+ // asynchronous transmit file.
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ u_long bytes_per_send_;
+
+ /// Flags which were passed into transmit file.
+ u_long flags_;
+};
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Transmit_File
+ *
+ * @brief Implementation for transmit_file will make use of
+ * POSIX_AIOCB_Asynch_Transmit_Handler.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Transmit_File : public virtual ACE_Asynch_Transmit_File_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Transmit_File (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+
+ /**
+ * This starts off an asynchronous transmit file. The <file> is a
+ * handle to an open file. <header_and_trailer> is a pointer to a
+ * data structure that contains pointers to data to send before and
+ * after the file data is sent. Set this parameter to 0 if you only
+ * want to transmit the file data. Upto <bytes_to_write> will be
+ * written to the <socket>. If you want to send the entire file,
+ * let <bytes_to_write> = 0. <bytes_per_send> is the size of each
+ * block of data sent per send operation. Please read the POSIX
+ * documentation on what the flags should be.
+ */
+ int transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Asynch_Transmit_File (void);
+
+ // = Methods belong to ACE_POSIX_Asynch_Operation base class. These
+ // methods are defined here to avoid dominace warnings. They route
+ // the call to the ACE_POSIX_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor = 0);
+
+ ///
+ /// @@ Not implemented. Returns 0.
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+};
+
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Read_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a UDP socket.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can be
+ * started using this class. An ACE_Asynch_Read_Dgram::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_stream>
+ * callback.
+ *
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Read_Dgram : public virtual ACE_Asynch_Read_Dgram_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Read_Dgram (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+ virtual ~ACE_POSIX_AIOCB_Asynch_Read_Dgram (void);
+
+ /** This starts off an asynchronous read. Upto
+ * <message_block->total_size()> will be read and stored in the
+ * <message_block>. <message_block>'s <wr_ptr> will be updated to reflect
+ * the added bytes if the read operation is successful completed.
+ * Return code of 1 means immediate success and number_of_bytes_recvd
+ * will contain number of bytes read. The <ACE_Handler::handle_read_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. <signal_number> argument is a no-op on non-POSIX4 systems.
+ */
+ virtual ssize_t recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number);
+
+ // Methods belong to ACE_POSIX_AIOCB_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_POSIX_AIOCB_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_POSIX_AIOCB_Asynch_Read_Dgram (void);
+};
+
+/**
+ * @class ACE_POSIX__Asynch_Write_Dgram_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Write_Dgram::Result class.
+ */
+class ACE_Export ACE_POSIX_Asynch_Write_Dgram_Result : public virtual ACE_Asynch_Write_Dgram_Result_Impl,
+ public ACE_POSIX_Asynch_Result
+{
+ /// Factory classes willl have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Write_Dgram;
+
+ /// Proactor class has special permission.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block which contains the sent data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The flags using in the write
+ int flags (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Write_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_Stream factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Write_Dgram_Result (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write_;
+
+ /// Message block used for the send.
+ ACE_Message_Block *message_block_;
+
+ /// The flags using in the write
+ int flags_;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle_;
+
+ };
+
+/**
+ * @class ACE_POSIX_AIOCB_Asynch_Write_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a UDP socket.
+ *
+ *
+ * Once <open> is called, multiple asynchronous <writes>s can
+ * started using this class. A ACE_Asynch_Write_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * write completes through the
+ * <ACE_Handler::handle_write_stream> callback.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Asynch_Write_Dgram : public virtual ACE_Asynch_Write_Dgram_Impl,
+ public ACE_POSIX_AIOCB_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_POSIX_AIOCB_Asynch_Write_Dgram (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+ virtual ~ACE_POSIX_AIOCB_Asynch_Write_Dgram (void);
+
+ /** This starts off an asynchronous send. Upto
+ * <message_block->total_length()> will be sent. <message_block>'s
+ * <rd_ptr> will be updated to reflect the sent bytes if the send operation
+ * is successful completed.
+ * Return code of 1 means immediate success and number_of_bytes_sent
+ * is updated to number of bytes sent. The <ACE_Handler::handle_write_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Priority of the operation is specified by <priority>. On POSIX4-Unix,
+ * this is supported. Works like <nice> in Unix. Negative values are not
+ * allowed. 0 means priority of the operation same as the process
+ * priority. 1 means priority of the operation is one less than
+ * process. And so forth. <signal_number> is a no-op on non-POSIX4 systems.
+ */
+ virtual ssize_t send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ const void *act,
+ int priority,
+ int signal_number);
+
+ // = Methods belonging to <ACE_POSIX_AIOCB_Asynch_Operation> base class.
+
+ // These methods are defined here to avoid VC++ warnings. They route
+ // the call to the <ACE_POSIX_AIOCB_Asynch_Operation> base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_POSIX_AIOCB_Asynch_Write_Dgram (void);
+};
+
+
+/*****************************************************/
+
+/**
+ * @class ACE_POSIX_Asynch_Read_Dgram_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Read_Dgram::Result class.
+ */
+class ACE_Export ACE_POSIX_Asynch_Read_Dgram_Result : public virtual ACE_Asynch_Read_Dgram_Result_Impl,
+ public virtual ACE_POSIX_Asynch_Result
+{
+
+ /// Factory classes will have special permissions.
+ friend class ACE_POSIX_AIOCB_Asynch_Read_Dgram;
+
+ /// Proactor class has special permission.
+ friend class ACE_POSIX_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The address of where the packet came from
+ int remote_address (ACE_Addr& addr) const;
+
+ sockaddr *saddr () const;
+
+ /// The flags used in the read
+ int flags (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ // Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_POSIX_Asynch_Read_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ u_long bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_Dgram factory.
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Read_Dgram_Result (void);
+
+ /// Bytes requested when the asynchronous read was initiated.
+ u_long bytes_to_read_;
+
+ /// Message block for reading the data into.
+ ACE_Message_Block *message_block_;
+
+ /// The address of where the packet came from
+ ACE_Addr *remote_address_;
+
+ int addr_len_;
+
+ /// The flags used in the read
+ int flags_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+
+};
+
+
+
+#if defined (__ACE_INLINE__)
+#include "ace/POSIX_Asynch_IO.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_AIO_CALLS */
+#endif /* ACE_POSIX_ASYNCH_IO_H */
diff --git a/ace/Connection/POSIX_Asynch_IO.i b/ace/Connection/POSIX_Asynch_IO.i
new file mode 100644
index 00000000000..6318deb79a0
--- /dev/null
+++ b/ace/Connection/POSIX_Asynch_IO.i
@@ -0,0 +1,2 @@
+/* -*- C++ -*- */
+// $Id$
diff --git a/ace/Connection/Sock_Connect.cpp b/ace/Connection/Sock_Connect.cpp
new file mode 100644
index 00000000000..8d11bdf2621
--- /dev/null
+++ b/ace/Connection/Sock_Connect.cpp
@@ -0,0 +1,1127 @@
+// $Id$
+
+#include "ace/Sock_Connect.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Handle_Set.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/SString.h"
+
+#if defined (VXWORKS)
+#include /**/ <inetLib.h>
+#include /**/ <netinet/in_var.h>
+extern "C" {
+ extern struct in_ifaddr* in_ifaddr;
+}
+#endif /* VXWORKS */
+
+#if defined (ACE_HAS_IPV6)
+# if defined (ACE_HAS_THREADS)
+# include "ace/Synch.h"
+# include "ace/Object_Manager.h"
+# endif /* ACE_HAS_THREADS */
+
+// Whether or not ipv6 is turned on in this box
+int ACE_Sock_Connect::ipv6_enabled_ = -1;
+#endif /* ACE_HAS_IPV6 */
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/Sock_Connect.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, Sock_Connect, "$Id$")
+
+#if defined (ACE_WIN32) && \
+ (!defined (ACE_HAS_WINSOCK2) \
+ || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)))
+
+static int
+get_reg_subkeys (const ACE_TCHAR *key,
+ ACE_TCHAR *buffer,
+ DWORD &buf_len)
+{
+ HKEY hk;
+ LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_READ,
+ &hk);
+
+ if (rc != ERROR_SUCCESS)
+ return -1;
+
+ ACE_TCHAR subkeyname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN;
+ FILETIME update_dummy;
+
+ DWORD total = 0;
+
+ for (int i = 0;
+ (rc = ACE_TEXT_RegEnumKeyEx (hk, i,
+ subkeyname,
+ &subkeyname_len,
+ 0, 0, 0,
+ &update_dummy)) != ERROR_NO_MORE_ITEMS;
+ ++i)
+ {
+ if (subkeyname_len < buf_len - total)
+ {
+ ACE_OS::strcpy(buffer + total, subkeyname);
+ total += subkeyname_len + 1;
+ // Reset: was changed by RegEnumKeyEx call.
+ subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ }
+ else
+ return -1;
+ }
+
+ buf_len = total;
+
+ ::RegCloseKey (hk);
+ return 0;
+}
+
+// Return value in buffer for a key/name pair from the Windows
+// Registry up to buf_len size.
+// If all_subkeys == 1, look for name under all subkeys of key.
+
+static int
+get_reg_value (const ACE_TCHAR *key,
+ const ACE_TCHAR *name,
+ ACE_TCHAR *buffer,
+ DWORD &buf_len,
+ int all_subkeys = 0)
+{
+ HKEY hk;
+ DWORD buf_type;
+ LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_READ,
+ &hk);
+
+ if (rc != ERROR_SUCCESS)
+ // print_error_string(ACE_LIB_TEXT ("RegOpenKeyEx"), rc);
+ return -1;
+
+ if (all_subkeys)
+ {
+ ACE_TCHAR ifname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ FILETIME update_dummy;
+
+ DWORD total = 0;
+ DWORD size = buf_len;
+
+ for (int i = 0;
+ (rc = ACE_TEXT_RegEnumKeyEx (hk, i, ifname, &ifname_len,
+ 0, 0, 0,
+ &update_dummy)) != ERROR_NO_MORE_ITEMS;
+ ++i)
+ {
+ HKEY ifkey;
+ if (rc != ERROR_SUCCESS
+ || ACE_TEXT_RegOpenKeyEx (hk, ifname, 0,
+ KEY_READ, &ifkey) != ERROR_SUCCESS)
+ continue;
+
+ if (ACE_TEXT_RegQueryValueEx (ifkey, name, 0, NULL,
+ (u_char*) (buffer + total),
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(ifkey);
+ continue;
+ }
+ else
+ {
+ total += size;
+ size = buf_len - total;
+ }
+ // Needs to be reset.
+ ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ }
+
+ if (total == 0)
+ {
+ ::RegCloseKey (hk);
+ return -2;
+ }
+ else
+ {
+ buf_len = total;
+ }
+ }
+ else
+ {
+
+ rc = ACE_TEXT_RegQueryValueEx (hk,
+ name,
+ 0,
+ &buf_type,
+ (u_char *) buffer,
+ &buf_len);
+ if (rc != ERROR_SUCCESS)
+ {
+ // print_error_string(ACE_LIB_TEXT ("RegEnumKeyEx"), rc);
+ RegCloseKey (hk);
+ return -2;
+ }
+ }
+
+ ::RegCloseKey (hk);
+ return 0;
+}
+
+enum ACE_WINDOWS_VERSION {
+ ACE_WINDOWS_IS_UNKNOWN,
+ ACE_WINDOWS_IS_WIN95,
+ ACE_WINDOWS_IS_WIN98,
+ ACE_WINDOWS_IS_WINME,
+ ACE_WINDOWS_IS_WINNT,
+ ACE_WINDOWS_IS_WIN2K
+};
+
+static ACE_WINDOWS_VERSION
+get_windows_version()
+{
+ OSVERSIONINFO vinfo;
+ vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (::GetVersionEx(&vinfo) == 0)
+ {
+ return ACE_WINDOWS_IS_UNKNOWN;
+ }
+
+ switch (vinfo.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_NT:
+ if (vinfo.dwMajorVersion <= 4)
+ return ACE_WINDOWS_IS_WINNT;
+ else
+ return ACE_WINDOWS_IS_WIN2K;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if (vinfo.dwMajorVersion == 4)
+ {
+ if (vinfo.dwMinorVersion == 0)
+ return ACE_WINDOWS_IS_WIN95;
+ else if (vinfo.dwMinorVersion == 10)
+ return ACE_WINDOWS_IS_WIN98;
+ else if (vinfo.dwMinorVersion == 90)
+ return ACE_WINDOWS_IS_WINME;
+ }
+ // If no match we fall throu.
+ default:
+ return ACE_WINDOWS_IS_UNKNOWN;
+ }
+}
+
+#endif //(ACE_WIN32) && !(ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)
+
+// Bind socket to an unused port.
+
+int
+ACE_Sock_Connect::bind_port (ACE_HANDLE handle,
+ ACE_UINT32 ip_addr)
+{
+ ACE_TRACE ("ACE_Sock_Connect::bind_port");
+
+ ACE_INET_Addr addr ((u_short)0, ip_addr);
+
+#if !defined (ACE_LACKS_WILDCARD_BIND)
+ // The OS kernel should select a free port for us.
+ return ACE_OS::bind (handle,
+ (sockaddr*)addr.get_addr(),
+ addr.get_size());
+#else
+ static u_short upper_limit = ACE_MAX_DEFAULT_PORT;
+ int round_trip = upper_limit;
+ int lower_limit = IPPORT_RESERVED;
+
+ // We have to select the port explicitly.
+
+ for (;;)
+ {
+ addr.set((u_short)upper_limit,ip_addr);
+
+ if (ACE_OS::bind (handle,
+ (sockaddr*)addr.get_addr()
+ addr.get_size()) >= 0)
+ {
+#if defined (ACE_WIN32)
+ upper_limit--;
+#endif /* ACE_WIN32 */
+ return 0;
+ }
+ else if (errno != EADDRINUSE)
+ return -1;
+ else
+ {
+ upper_limit--;
+
+ // Wrap back around when we reach the bottom.
+ if (upper_limit <= lower_limit)
+ upper_limit = ACE_MAX_DEFAULT_PORT;
+
+ // See if we have already gone around once!
+ if (upper_limit == round_trip)
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+ }
+ }
+#endif /* ACE_HAS_WILDCARD_BIND */
+}
+
+int
+ACE_Sock_Connect::get_bcast_addr (ACE_UINT32 &bcast_addr,
+ const ACE_TCHAR *host_name,
+ ACE_UINT32 host_addr,
+ ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Sock_Connect::get_bcast_addr");
+
+#if !defined(ACE_WIN32)
+ ACE_HANDLE s = handle;
+
+ if (s == ACE_INVALID_HANDLE)
+ s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
+
+ if (s == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_OS::socket")),
+ -1);
+
+ struct ifconf ifc;
+ char buf[BUFSIZ];
+
+ ifc.ifc_len = sizeof buf;
+ ifc.ifc_buf = buf;
+
+ // Get interface structure and initialize the addresses using UNIX
+ // techniques
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (s, cmd, (char *) &ifc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT ("ioctl (get interface configuration)")),
+ -1);
+
+ struct ifreq *ifr = ifc.ifc_req;
+
+ struct sockaddr_in ip_addr;
+
+ // Get host ip address if necessary.
+ if (host_name)
+ {
+ hostent *hp = ACE_OS::gethostbyname (host_name);
+
+ if (hp == 0)
+ return -1;
+ else
+#if !defined(_UNICOS)
+ ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
+ (char *) hp->h_addr,
+ hp->h_length);
+#else /* _UNICOS */
+ {
+ ACE_UINT64 haddr; // a place to put the address
+ char * haddrp = (char *) &haddr; // convert to char pointer
+ ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
+ ip_addr.sin_addr.s_addr = haddr;
+ }
+#endif /* ! _UNICOS */
+ }
+ else
+ {
+ ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
+#if !defined(_UNICOS)
+ ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
+ (void*) &host_addr,
+ sizeof ip_addr.sin_addr);
+#else /* _UNICOS */
+ ip_addr.sin_addr.s_addr = host_addr; // just copy to the bitfield
+#endif /* ! _UNICOS */
+ }
+
+ for (int n = ifc.ifc_len / sizeof (struct ifreq);
+ n > 0;
+#if !defined(CHORUS_4)
+ n--, ifr++)
+#else
+ n--,
+ ((ifr->ifr_addr.sa_len <= sizeof (struct sockaddr)) ?
+ ifr++ :
+ ifr = (struct ifreq *)
+ (ifr->ifr_addr.sa_len + (caddr_t) &ifr->ifr_addr)))
+#endif /* CHORUS_4 */
+ {
+ struct sockaddr_in if_addr;
+
+ // Compare host ip address with interface ip address.
+ ACE_OS::memcpy (&if_addr,
+ &ifr->ifr_addr,
+ sizeof if_addr);
+
+ if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
+ continue;
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT ("Not AF_INET")));
+ continue;
+ }
+
+ struct ifreq flags = *ifr;
+ struct ifreq if_req = *ifr;
+
+ if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT (" ioctl (get interface flags)")));
+ continue;
+ }
+
+ if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT ("Network interface is not up")));
+ continue;
+ }
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
+ continue;
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
+ {
+ if (ACE_OS::ioctl (s,
+ SIOCGIFBRDADDR,
+ (char *) &if_req) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT ("ioctl (get broadaddr)")));
+ else
+ {
+ ACE_OS::memcpy (ACE_reinterpret_cast(sockaddr_in *, &ip_addr),
+ ACE_reinterpret_cast(sockaddr_in *, &if_req.ifr_broadaddr),
+ sizeof if_req.ifr_broadaddr);
+
+ ACE_OS::memcpy ((void *) &host_addr,
+ (void *) &ip_addr.sin_addr,
+ sizeof host_addr);
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_OS::close (s);
+
+ bcast_addr = host_addr;
+ return 0;
+ }
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_bcast_addr:")
+ ACE_LIB_TEXT ("Broadcast is not enable for this interface.")));
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_OS::close (s);
+
+ bcast_addr = host_addr;
+ return 0;
+ }
+
+ return 0;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (host_addr);
+ ACE_UNUSED_ARG (host_name);
+ bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
+ return 0;
+#endif /* !ACE_WIN32 */
+}
+
+// return an array of all configured IP interfaces on this host, count
+// rc = 0 on success (count == number of interfaces else -1 caller is
+// responsible for calling delete [] on parray
+
+int
+ACE_Sock_Connect::get_ip_interfaces (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ ACE_TRACE ("ACE_Sock_Connect::get_ip_interfaces");
+
+ count = 0;
+ addrs = 0;
+
+#if defined (ACE_WIN32)
+ // Win32 can do this by a simple API call if MSVC 5 or later is the compiler.
+ // Not sure if Borland supplies the needed header/lib, but it might.
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ int i, n_interfaces, status;
+
+ INTERFACE_INFO info[64];
+ SOCKET sock;
+
+ // Get an (overlapped) DGRAM socket to test with
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sock == INVALID_SOCKET)
+ return -1;
+
+ DWORD bytes;
+ status = WSAIoctl(sock,
+ SIO_GET_INTERFACE_LIST,
+ 0,
+ 0,
+ info,
+ sizeof(info),
+ &bytes,
+ 0,
+ 0);
+ closesocket (sock);
+ if (status == SOCKET_ERROR)
+ return -1;
+
+ n_interfaces = bytes / sizeof(INTERFACE_INFO);
+ if (n_interfaces == 0)
+ return 0;
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces],
+ -1);
+
+ // Now go through the list and transfer the good ones to the list of
+ // because they're down or don't have an IP address.
+ for (count = 0, i = 0; i < n_interfaces; i++)
+ {
+ LPINTERFACE_INFO lpii;
+ struct sockaddr_in *addrp;
+
+ lpii = &info[i];
+ if (!(lpii->iiFlags & IFF_UP))
+ continue;
+
+ // We assume IPv4 addresses here
+ addrp = ACE_reinterpret_cast(struct sockaddr_in *, &(lpii->iiAddress));
+ if (addrp->sin_addr.s_addr == INADDR_ANY)
+ continue;
+
+ // Set the address for the caller.
+ addrs[count].set(addrp, sizeof(sockaddr_in));
+ ++count;
+ }
+
+ if (count == 0)
+ {
+ delete [] addrs;
+ addrs = 0;
+ }
+
+ return 0;
+
+#else /* Winsock 2 && MSVC 5 or later */
+
+ // PharLap ETS has kernel routines to rummage through the device
+ // configs and extract the interface info. Sort of a pain in the
+ // butt, but better than trying to figure out where it moved to in
+ // the registry... :-|
+# if defined (ACE_HAS_PHARLAP)
+# if !defined (ACE_HAS_PHARLAP_RT)
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PHARLAP_RT */
+
+ // Locate all of the IP devices in the system, saving a DEVHANDLE
+ // for each. Then allocate the ACE_INET_Addrs needed and fetch all
+ // the IP addresses. To locate the devices, try the available
+ // device name roots and increment the device number until the
+ // kernel says there are no more of that type.
+ const size_t ACE_MAX_ETS_DEVICES = 64; // Arbitrary, but should be enough.
+ DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
+ EK_TCPIPCFG *devp;
+ size_t i, j;
+ ACE_TCHAR dev_name[16];
+
+ count = 0;
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // Ethernet.
+ ACE_OS::sprintf (dev_name,
+ "ether%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // SLIP.
+ ACE_OS::sprintf (dev_name,
+ "sl%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // PPP.
+ ACE_OS::sprintf (dev_name,
+ "ppp%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+
+ if (count > 0)
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[count],
+ -1);
+ else
+ addrs = 0;
+
+ for (i = 0, j = 0; i < count; i++)
+ {
+ devp = EtsTCPGetDeviceCfg (ip_dev[i]);
+ if (devp != 0)
+ {
+ addrs[j].set (0,
+ devp->nwIPAddress,
+ 0); // Already in net order.
+ j++;
+ }
+ // There's no call to close the DEVHANDLE.
+ }
+
+ count = j;
+ if (count == 0 && addrs != 0)
+ {
+ delete [] addrs;
+ addrs = 0;
+ }
+
+ return 0;
+
+# else /* ACE_HAS_PHARLAP */
+
+ //
+ // No Winsock2.
+ // Get interface information from the registry.
+ // As this information is in different locations of the registry
+ // on different windows versions, we need to ask at runtime.
+ //
+
+ // Normally we have to look under one key for interfaces name,
+ // and under a second key for ip address of those interfaces.
+ // Exact values and the way to search depend on windows version.
+
+ // This is the first key we have to look for.
+ const ACE_TCHAR *BASE_KEY1;
+
+ // This is the name we have to look for under the first key.
+ // If this is == 0, we need to look for subkeys, not the values from
+ // a name.
+ const ACE_TCHAR *KEY1_NAME_ID;
+
+ // The second key is normally constructed concatenating a prefix,
+ // the value found on KEY1_NAME_ID stripped from the first s_offset
+ // characters, and a suffix.
+ unsigned int s_offset;
+ const ACE_TCHAR *PREFFIX_KEY2;
+ const ACE_TCHAR *SUFFIX_KEY2;
+
+ // If != 0, look for the value of KEY1_NAME_ID not directly under
+ // BASE_KEY1, but on every subkey of BASE_KEY1.
+ int use_subkeys;
+
+ // When we search for IP Addresses below, we look for a key with a
+ // name in this array (null terminated).
+ // For some windows versions, there is an
+ // aditional key for ppp interfaces that will be stored on [1].
+ const ACE_TCHAR *IPADDR_NAME_ID[3] = {
+ ACE_LIB_TEXT ("IPAddress"), 0, 0
+ };
+
+ // Skip addresses that match this.
+ const ACE_TCHAR *INVALID_TCPIP_DEVICE_ADDR = ACE_LIB_TEXT ("0.0.0.0");
+
+ ACE_WINDOWS_VERSION winver = get_windows_version();
+
+ switch (winver)
+ {
+ case ACE_WINDOWS_IS_WINNT:
+ PREFFIX_KEY2 = ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\");
+ BASE_KEY1 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
+ ACE_LIB_TEXT ("\\Tcpip\\Linkage");
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("\\Parameters\\Tcpip");
+ KEY1_NAME_ID = ACE_LIB_TEXT ("Bind");
+ s_offset = 8;
+ use_subkeys = 0;
+ break;
+
+ case ACE_WINDOWS_IS_WIN2K:
+ BASE_KEY1 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
+ ACE_LIB_TEXT ("\\Tcpip\\Parameters\\Interfaces\\");
+ PREFFIX_KEY2 = BASE_KEY1;
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("");
+ KEY1_NAME_ID = 0;
+ s_offset = 0;
+ use_subkeys = 1;
+ // PPP.
+ IPADDR_NAME_ID[1] = ACE_LIB_TEXT ("DhcpIPAddress");
+ break;
+
+ // If ACE_HAS_WINNT4 we can safely assume the ones below will
+ // not be needed.
+# if !defined(ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0)
+ case ACE_WINDOWS_IS_WIN95:
+ case ACE_WINDOWS_IS_WIN98:
+ case ACE_WINDOWS_IS_WINME:
+ PREFFIX_KEY2 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\Class\\");
+ BASE_KEY1 = ACE_LIB_TEXT ("Enum\\Network\\MSTCP");
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("");
+ KEY1_NAME_ID = ACE_LIB_TEXT ("Driver");
+ use_subkeys = 1;
+ s_offset = 0;
+ break;
+# endif /* !ACE_HAS_WINNT4 */
+
+ default:
+ return -1;
+ }
+
+ ACE_TCHAR raw_buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD raw_buflen = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+
+ if (KEY1_NAME_ID == 0)
+ {
+ if (::get_reg_subkeys (BASE_KEY1,
+ raw_buffer,
+ raw_buflen))
+ return -1;
+ }
+ else
+ {
+ if (::get_reg_value (BASE_KEY1,
+ KEY1_NAME_ID,
+ raw_buffer,
+ raw_buflen,
+ use_subkeys))
+ return -1;
+ }
+ // return buffer contains 0 delimited strings
+
+ ACE_Tokenizer dev_names (raw_buffer);
+ dev_names.delimiter (ACE_LIB_TEXT ('\0'));
+ int n_interfaces = 0;
+
+ // Count the number of interfaces
+ while (dev_names.next () != 0)
+ n_interfaces ++;
+
+ // case 1. no interfaces present, empty string? OS version change?
+ if (n_interfaces == 0)
+ return 0;
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces],
+ -2);
+
+ ACE_TCHAR buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD buf_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+
+ count = 0;
+ for (int i = 0; i < n_interfaces; i++)
+ {
+ for (const ACE_TCHAR **ipaddr_name_id = IPADDR_NAME_ID;
+ *ipaddr_name_id != 0;
+ ++ipaddr_name_id)
+ {
+ // a. construct name to access IP Address for this interface
+ ACE_TString ifdevkey (PREFFIX_KEY2);
+ ACE_TString the_dev = dev_names.next ();
+
+ if (the_dev.length() < s_offset)
+ {
+ return -3; // Something's wrong
+ }
+
+ // rest of string from offset.
+ the_dev = the_dev.substring (s_offset);
+
+ ifdevkey += the_dev;
+ ifdevkey += SUFFIX_KEY2;
+
+ // b. extract value
+ // Gets overwritten on each call
+ buf_len = sizeof (buffer);
+ if (get_reg_value (ifdevkey.fast_rep (),
+ *ipaddr_name_id,
+ buffer,
+ buf_len))
+ continue; // Skip unknown devices.
+
+ if (ACE_OS::strcmp (buffer,
+ INVALID_TCPIP_DEVICE_ADDR) == 0)
+ continue; // Don't count this device
+
+ // c. store in hostinfo object array and up the counter
+ addrs[count++] =
+ ACE_INET_Addr ((u_short) 0, buffer);
+ }
+ }
+
+ return 0;
+# endif /* ACE_HAS_PHARLAP */
+# endif /* Winsock 2 && MSVC 5 or later */
+
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__MACOSX__)
+ // COMMON (SVR4 and BSD) UNIX CODE
+
+ size_t num_ifs;
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = get_handle();
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_ip_interfaces:open")),
+ -1);
+ if (ACE_Sock_Connect::count_interfaces (handle, num_ifs))
+ {
+ ACE_OS::close (handle);
+ return -1;
+ }
+
+ // ioctl likes to have an extra ifreq structure to mark the end of
+ // what it returned, so increase the num_ifs by one.
+ ++num_ifs;
+
+ struct ifreq *ifs = 0;
+ ACE_NEW_RETURN (ifs,
+ struct ifreq[num_ifs],
+ -1);
+ ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
+
+ ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
+
+ if (p_ifs.get() == 0)
+ {
+ ACE_OS::close (handle);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ struct ifconf ifcfg;
+ ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
+ ifcfg.ifc_req = p_ifs.get ();
+ ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
+
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#elif defined (__MACOSX__)
+ int cmd = OSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (handle,
+ cmd,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("get_ip_interfaces:")
+ ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")),
+ -1);
+ }
+
+ ACE_OS::close (handle);
+
+ // Now create and initialize output array.
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[num_ifs],
+ -1); // caller must free
+
+ struct ifreq *pcur = p_ifs.get ();
+ // Pull the address out of each INET interface. Not every interface
+ // is for IP, so be careful to count properly. When setting the
+ // INET_Addr, note that the 3rd arg (0) says to leave the byte order
+ // (already in net byte order from the interface structure) as is.
+ count = 0;
+
+ for (size_t i = 0;
+ i < num_ifs;
+ i++)
+ {
+ if (pcur->ifr_addr.sa_family == AF_INET)
+ {
+#if !defined(_UNICOS)
+ struct sockaddr_in *addr =
+ ACE_reinterpret_cast(sockaddr_in *, &pcur->ifr_addr);
+
+ // Sometimes the kernel returns 0.0.0.0 as the interface
+ // address, skip those...
+ if (addr->sin_addr.s_addr != 0)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ count++;
+ }
+#else /* ! _UNICOS */
+ // need to explicitly copy on the Cray, since the bitfields kinda
+ // screw things up here
+ struct sockaddr_in inAddr;
+
+ inAddr.sin_len = pcur->ifr_addr.sa_len;
+ inAddr.sin_family = pcur->ifr_addr.sa_family;
+ memcpy((void *)&(inAddr.sin_addr),
+ (const void *)&(pcur->ifr_addr.sa_data[8]),
+ sizeof(struct in_addr));
+
+ if (inAddr.sin_addr.s_addr != 0)
+ {
+ addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
+ count++;
+ }
+#endif /* ! _UNICOS */
+ }
+
+#if !defined(CHORUS_4)
+ pcur++;
+#else
+ if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
+ {
+ pcur++;
+ }
+ else
+ {
+ pcur = (struct ifreq *)
+ (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
+ }
+#endif
+ }
+ return 0;
+#elif defined (VXWORKS)
+ count = 0;
+ // Loop through each address structure
+ for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
+ {
+ ++count;
+ }
+
+ // Now create and initialize output array.
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[count],
+ -1); // caller must free
+ count = 0;
+ for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
+ {
+ struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
+ if (ifp != 0)
+ {
+ // Get the current interface name
+ char interface[64];
+ ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
+
+ // Get the address for the current interface
+ char address [INET_ADDR_LEN];
+ STATUS status = ifAddrGet(interface, address);
+
+ if (status == OK)
+ {
+ // Concatenate a ':' at the end. This is because in
+ // ACE_INET_Addr::string_to_addr, the ip_address is
+ // obtained using ':' as the delimiter. Since, using
+ // ifAddrGet(), we just get the IP address, I am adding
+ // a ":" to get with the general case.
+ ACE_OS::strcat (address, ":");
+ addrs[count].set (address);
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE::get_ip_interface failed\n"),
+ ACE_LIB_TEXT ("Couldnt get the IP Address\n")),
+ -1);
+ }
+ ++count;
+ }
+ }
+ return 0;
+#else
+ ACE_UNUSED_ARG (count);
+ ACE_UNUSED_ARG (addrs);
+ ACE_NOTSUP_RETURN (-1);; // no implementation
+#endif /* ACE_WIN32 */
+}
+
+// Helper routine for get_ip_interfaces, differs by UNIX platform so
+// put into own subroutine. perform some ioctls to retrieve ifconf
+// list of ifreq structs.
+
+int
+ACE_Sock_Connect::count_interfaces (ACE_HANDLE handle, size_t &how_many)
+{
+#if defined (sparc) && defined (SIOCGIFNUM)
+ int tmp_how_many; // For 64 bit Solaris
+ if (ACE_OS::ioctl (handle,
+ SIOCGIFNUM,
+ (caddr_t) &tmp_how_many) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_Sock_Connect::get_ip_interfaces:")
+ ACE_LIB_TEXT ("ioctl - SIOCGIFNUM failed")),
+ -1);
+ how_many = (size_t) tmp_how_many;
+ return 0;
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__MACOSX__)
+ // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
+ // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
+ // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
+ // algorithm
+
+ // Probably hard to put this many ifs in a unix box..
+ const int MAX_IF = 50;
+
+ // HACK - set to an unreasonable number
+ int num_ifs = MAX_IF;
+
+ struct ifconf ifcfg;
+ size_t ifreq_size = num_ifs * sizeof (struct ifreq);
+ struct ifreq *p_ifs =
+ (struct ifreq *) ACE_OS::malloc (ifreq_size);
+
+ if (!p_ifs)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ACE_OS::memset (p_ifs, 0, ifreq_size);
+ ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
+
+ ifcfg.ifc_req = p_ifs;
+ ifcfg.ifc_len = ifreq_size;
+
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (handle,
+ cmd,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::free (ifcfg.ifc_req);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("count_interfaces:ioctl:")
+ ACE_LIB_TEXT ("SIOCGIFCONF failed")),
+ -1);
+ }
+
+ int if_count = 0, i;
+
+ // get if address out of ifreq buffers. ioctl puts a blank-named
+ // interface to mark the end of the returned interfaces.
+ for (i = 0;
+ i < num_ifs;
+ i++)
+ {
+ if (p_ifs->ifr_name[0] == '\0')
+ break;
+
+ if_count++;
+#if !defined(CHORUS_4)
+ p_ifs++;
+#else
+ if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
+ {
+ p_ifs++;
+ }
+ else
+ {
+ p_ifs = (struct ifreq *)
+ (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
+ }
+#endif /* CHORUS_4 */
+ }
+
+ ACE_OS::free (ifcfg.ifc_req);
+ how_many = if_count;
+ return 0;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (how_many);
+ ACE_NOTSUP_RETURN (-1);; // no implmentation
+#endif /* sparc && SIOCGIFNUM */
+}
+
+// Routine to return a handle from which ioctl() requests can be made.
+
+ACE_HANDLE
+ACE_Sock_Connect::get_handle (void)
+{
+ // Solaris 2.x
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+#if defined (sparc) && ! defined (CHORUS)
+ handle = ACE_OS::open ("/dev/udp", O_RDONLY);
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__MACOSX__)
+ // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
+ // AIX, SunOS 4.x
+
+ handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
+#endif /* sparc */
+ return handle;
+}
+
+
+int
+ACE_Sock_Connect::ipv6_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ if (ACE_Sock_Connect::ipv6_enabled_ == -1)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ACE_Sock_Connect::ipv6_enabled_ == -1)
+ {
+ // Determine if the kernel has IPv6 support by attempting to
+ // create a PF_INET6 socket and see if it fails.
+ ACE_HANDLE s = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
+ if (s == ACE_INVALID_HANDLE)
+ {
+ ACE_Sock_Connect::ipv6_enabled_ = 0;
+ }
+ else
+ {
+ ACE_Sock_Connect::ipv6_enabled_ = 1;
+ ACE_OS::closesocket (s);
+ }
+ }
+ }
+
+ return ACE_Sock_Connect::ipv6_enabled_;
+#else
+ return 0;
+#endif /* ACE_HAS_IPV6 */
+}
diff --git a/ace/Connection/Sock_Connect.h b/ace/Connection/Sock_Connect.h
new file mode 100644
index 00000000000..931cb1975ef
--- /dev/null
+++ b/ace/Connection/Sock_Connect.h
@@ -0,0 +1,89 @@
+//=============================================================================
+/**
+ * @file Sock_Connect.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_CONNECT_H
+#define ACE_SOCK_CONNECT_H
+#include "ace/pre.h"
+
+#include "ace/OS/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward Declarations
+class ACE_INET_Addr;
+
+class ACE_Export ACE_Sock_Connect
+{
+ public:
+
+ // = Socket connection establishment calls.
+
+ /// Bind a new unused port to <handle>.
+ static int bind_port (ACE_HANDLE handle,
+ ACE_UINT32 ip_addr = INADDR_ANY);
+
+ /**
+ * Get our broadcast address based on our <host_addr>. If
+ * <hostname> is non-0 we'll use it to determine our IP address. If
+ * <handle> is not <ACE_INVALID_HANDLE> then we'll use this to
+ * determine our broadcast address, otherwise we'll have to create a
+ * socket internally (and free it). Returns -1 on failure and 0 on
+ * success.
+ */
+ static int get_bcast_addr (ACE_UINT32 &bcast_addr,
+ const ACE_TCHAR *hostname = 0,
+ ACE_UINT32 host_addr = 0,
+ ACE_HANDLE handle = ACE_INVALID_HANDLE);
+
+ /**
+ * Return count and array of all configured IP interfaces on this
+ * host, rc = 0 on success (count == number of interfaces else -1).
+ * Caller is responsible for calling delete [] on <addr_array>.
+ */
+ static int get_ip_interfaces (size_t &count,
+ ACE_INET_Addr *&addr_array);
+
+ /**
+ * Helper routine for get_ip_interfaces, differs by UNIX platform so
+ * put into own subroutine. perform some ioctls to retrieve ifconf
+ * list of ifreq structs.
+ */
+ static int count_interfaces (ACE_HANDLE handle,
+ size_t &how_many);
+
+ /// Routine to return a handle from which <ioctl> requests can be
+ /// made. Caller must <close> the handle.
+ static ACE_HANDLE get_handle (void);
+
+ /**
+ * Returns 1 if IPv6 is enabled on the current host; 0 if not.
+ * This is an execution-time check. If ACE has not been compiled
+ * with ACE_HAS_IPV6, it always returns 0. If ACE_HAS_IPV6 is
+ * enabled, this function tries to create a PF_INET6 socket,
+ * returning 1 if it succeeds, and 0 if it fails. Caches the result
+ * so it only gets checked once.
+ */
+ static int ipv6_enabled (void);
+
+#if defined (ACE_HAS_IPV6)
+private:
+ /// Does this box have ipv6 turned on?
+ static int ipv6_enabled_;
+#endif /* ACE_HAS_IPV6 */
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "Sock_Connect.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_CONNECT_H */
diff --git a/ace/Connection/Sock_Connect.i b/ace/Connection/Sock_Connect.i
new file mode 100644
index 00000000000..cfa1da318d3
--- /dev/null
+++ b/ace/Connection/Sock_Connect.i
@@ -0,0 +1 @@
+// $Id$
diff --git a/ace/Connection/Strategies_T.cpp b/ace/Connection/Strategies_T.cpp
new file mode 100644
index 00000000000..70924c3bc31
--- /dev/null
+++ b/ace/Connection/Strategies_T.cpp
@@ -0,0 +1,1230 @@
+// $Id$
+
+#ifndef ACE_STRATEGIES_T_C
+#define ACE_STRATEGIES_T_C
+
+#include "ace/Strategies_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Repository.h"
+#include "ace/Synch.h"
+#include "ace/Service_Types.h"
+#include "ace/Thread_Manager.h"
+#include "ace/WFMO_Reactor.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/Strategies_T.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, Strategies_T, "$Id$")
+
+template <class SVC_HANDLER> int
+ACE_Singleton_Strategy<SVC_HANDLER>::open (SVC_HANDLER *sh,
+ ACE_Thread_Manager *)
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::open");
+
+ if (this->delete_svc_handler_
+ && this->svc_handler_ != 0)
+ delete this->svc_handler_;
+
+ // If <sh> is NULL then create a new <SVC_HANDLER>.
+ if (sh == 0)
+ {
+ ACE_NEW_RETURN (this->svc_handler_,
+ SVC_HANDLER,
+ -1);
+ this->delete_svc_handler_ = 1;
+ }
+ else
+ {
+ this->svc_handler_ = sh;
+ this->delete_svc_handler_ = 0;
+ }
+
+ return 0;
+}
+
+template <class SVC_HANDLER> int
+ACE_DLL_Strategy<SVC_HANDLER>::open (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
+ ACE_Service_Repository *svc_rep,
+ ACE_Thread_Manager *thr_mgr)
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::open");
+ this->inherited::open (thr_mgr);
+ ACE_OS::strcpy (this->dll_name_, dll_name);
+ ACE_OS::strcpy (this->factory_function_, factory_function);
+ ACE_OS::strcpy (this->svc_name_, svc_name);
+ this->svc_rep_ = svc_rep;
+ return 0;
+}
+
+// Create a SVC_HANDLER by dynamically linking it from a DLL.
+
+template <class SVC_HANDLER> int
+ACE_DLL_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::make_svc_handler");
+
+ // Open the shared library.
+ ACE_SHLIB_HANDLE handle = ACE_OS::dlopen (this->shared_library_);
+
+ // Extract the factory function.
+ SVC_HANDLER *(*factory)(void) =
+ (SVC_HANDLER *(*)(void)) ACE_OS::dlsym (handle,
+ this->factory_function_);
+
+ // Call the factory function to obtain the new SVC_Handler (should
+ // use RTTI here when it becomes available...)
+ SVC_HANDLER *svc_handler;
+
+ ACE_ALLOCATOR_RETURN (svc_handler, (*factory)(), -1);
+
+ if (svc_handler != 0)
+ {
+ // Create an ACE_Service_Type containing the SVC_Handler and
+ // insert into this->svc_rep_;
+
+ ACE_Service_Type_Impl *stp;
+ ACE_NEW_RETURN (stp,
+ ACE_Service_Object_Type (svc_handler,
+ this->svc_name_),
+ -1);
+
+ ACE_Service_Type *srp = 0;
+
+ ACE_NEW_RETURN (srp,
+ ACE_Service_Type (this->svc_name_,
+ stp,
+ handle,
+ 1),
+ -1);
+ if (srp == 0)
+ {
+ delete stp;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (this->svc_rep_->insert (srp) == -1)
+ return -1;
+ // @@ Somehow, we need to deal with this->thr_mgr_...
+ }
+
+ sh = svc_handler;
+ return 0;
+}
+
+// Default behavior is to activate the SVC_HANDLER by calling it's
+// open() method, which allows the SVC_HANDLER to determine its own
+// concurrency strategy.
+
+template <class SVC_HANDLER> int
+ACE_Concurrency_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg)
+{
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::activate_svc_handler");
+
+ int result = 0;
+
+ // See if we should enable non-blocking I/O on the <svc_handler>'s
+ // peer.
+ if (ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK) != 0)
+ {
+ if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
+ result = -1;
+ }
+ // Otherwise, make sure it's disabled by default.
+ else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
+ result = -1;
+
+ if (result == 0 && svc_handler->open (arg) == -1)
+ result = -1;
+
+ if (result == -1)
+ svc_handler->close (0);
+
+ return result;
+}
+
+template <class SVC_HANDLER> int
+ACE_Reactive_Strategy<SVC_HANDLER>::open (ACE_Reactor *reactor,
+ ACE_Reactor_Mask mask,
+ int flags)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::open");
+ this->reactor_ = reactor;
+ this->mask_ = mask;
+ this->flags_ = flags;
+
+ // Must have a <Reactor>
+ if (this->reactor_ == 0)
+ return -1;
+ else
+ return 0;
+}
+
+template <class SVC_HANDLER> int
+ACE_Reactive_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::activate_svc_handler");
+
+ int result = 0;
+
+ if (this->reactor_ == 0)
+ result = -1;
+
+ // Register with the Reactor with the appropriate <mask>.
+ else if (this->reactor_->register_handler (svc_handler, this->mask_) == -1)
+ result = -1;
+
+ // If the implementation of the reactor uses event associations
+ else if (this->reactor_->uses_event_associations ())
+ {
+ // If we don't have non-block on, it won't work with
+ // WFMO_Reactor
+ // This maybe too harsh
+ // if (!ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK))
+ // goto failure;
+ if (svc_handler->open (arg) != -1)
+ return 0;
+ else
+ result = -1;
+ }
+ else
+ // Call up to our parent to do the SVC_HANDLER initialization.
+ return this->inherited::activate_svc_handler (svc_handler, arg);
+
+ if (result == -1)
+ svc_handler->close (0);
+
+ return result;
+}
+
+template <class SVC_HANDLER> int
+ACE_Thread_Strategy<SVC_HANDLER>::open (ACE_Thread_Manager *thr_mgr,
+ long thr_flags,
+ size_t n_threads,
+ int flags)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::open");
+ this->thr_mgr_ = thr_mgr;
+ this->n_threads_ = n_threads;
+ this->thr_flags_ = thr_flags;
+ this->flags_ = flags;
+
+ // Must have a thread manager!
+ if (this->thr_mgr_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("error: must have a non-NULL thread manager\n")),
+ -1);
+ else
+ return 0;
+}
+
+template <class SVC_HANDLER> int
+ACE_Thread_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::activate_svc_handler");
+ // Call up to our parent to do the SVC_HANDLER initialization.
+ if (this->inherited::activate_svc_handler (svc_handler,
+ arg) == -1)
+ return -1;
+ else
+ // Turn the <svc_handler> into an active object (if it isn't
+ // already one as a result of the first activation...)
+ return svc_handler->activate (this->thr_flags_,
+ this->n_threads_);
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr, int reuse_addr)
+{
+ this->reuse_addr_ = reuse_addr;
+ this->peer_acceptor_addr_ = local_addr;
+ if (this->peer_acceptor_.open (local_addr,
+ reuse_addr) == -1)
+ return -1;
+
+ // Set the peer acceptor's handle into non-blocking mode. This is a
+ // safe-guard against the race condition that can otherwise occur
+ // between the time when <select> indicates that a passive-mode
+ // socket handle is "ready" and when we call <accept>. During this
+ // interval, the client can shutdown the connection, in which case,
+ // the <accept> call can hang!
+ this->peer_acceptor_.enable (ACE_NONBLOCK);
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Accept_Strategy
+ (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ int reuse_addr,
+ ACE_Reactor *reactor)
+ : reactor_ (reactor)
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Accept_Strategy");
+
+ if (this->open (local_addr, reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("open")));
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler");
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle = this->reactor_->uses_event_associations ();
+
+ if (this->peer_acceptor_.accept (svc_handler->peer (), // stream
+ 0, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle // reset new handler
+ ) == -1)
+ {
+ // Close down handler to avoid memory leaks.
+ svc_handler->close (0);
+
+ return -1;
+ }
+ else
+ return 0;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
+
+ return this->connector_.connect (sh->peer (),
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
+(SVC_HANDLER *&sh,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
+
+ int result =
+ this->connector_.connect (sh->peer (),
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+ sh_copy = sh;
+ return result;
+}
+
+template <class SVC_HANDLER> int
+ACE_Process_Strategy<SVC_HANDLER>::open (size_t n_processes,
+ ACE_Event_Handler *acceptor,
+ ACE_Reactor *reactor,
+ int avoid_zombies)
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::open");
+ this->n_processes_ = n_processes;
+ this->acceptor_ = acceptor;
+ this->reactor_ = reactor;
+ this->flags_ = avoid_zombies;
+
+ return 0;
+}
+
+template <class SVC_HANDLER> int
+ACE_Process_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg)
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::activate_svc_handler");
+
+ // If <flags_> is non-0 then we won't create zombies.
+ switch (ACE::fork (ACE_LIB_TEXT ("child"), this->flags_))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("fork")),
+ -1);
+ /* NOTREACHED */
+ case 0: // In child process.
+
+ // Close down the SOCK_Acceptor's handle since we don't need to
+ // keep it open.
+ if (this->acceptor_ != 0)
+ // Ignore the return value here...
+ (void) this->reactor_->remove_handler (this->acceptor_,
+ ACE_Event_Handler::ACCEPT_MASK);
+
+ // Call up to our ancestor in the inheritance to do the
+ // SVC_HANDLER initialization.
+ return this->inherited::activate_svc_handler (svc_handler, arg);
+ /* NOTREACHED */
+ default: // In parent process.
+ // We need to close down the <SVC_HANDLER> here because it's
+ // running in the child.
+ svc_handler->destroy ();
+ return 0;
+ }
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX>
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::ACE_Cached_Connect_Strategy
+(ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Recycling_Strategy<SVC_HANDLER> *rec_s,
+ MUTEX *lock,
+ int delete_lock)
+ : lock_ (lock),
+ delete_lock_ (delete_lock),
+ reverse_lock_ (0),
+ creation_strategy_ (0),
+ delete_creation_strategy_ (0),
+ concurrency_strategy_ (0),
+ delete_concurrency_strategy_ (0),
+ recycling_strategy_ (0),
+ delete_recycling_strategy_ (0)
+{
+ // Create a new lock if necessary.
+ if (this->lock_ == 0)
+ {
+ ACE_NEW (this->lock_,
+ MUTEX);
+
+ this->delete_lock_ = 1;
+ }
+
+ ACE_NEW (this->reverse_lock_,
+ REVERSE_MUTEX (*this->lock_));
+
+ if (this->open (cre_s,
+ con_s,
+ rec_s) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Cached_Connect_Strategy::ACE_Cached_Connect_Strategy")));
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX>
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::~ACE_Cached_Connect_Strategy (void)
+{
+ if (this->delete_lock_)
+ delete this->lock_;
+
+ delete this->reverse_lock_;
+
+ if (this->delete_creation_strategy_)
+ delete this->creation_strategy_;
+ this->delete_creation_strategy_ = 0;
+ this->creation_strategy_ = 0;
+
+ if (this->delete_concurrency_strategy_)
+ delete this->concurrency_strategy_;
+ this->delete_concurrency_strategy_ = 0;
+ this->concurrency_strategy_ = 0;
+
+ if (this->delete_recycling_strategy_)
+ delete this->recycling_strategy_;
+ this->delete_recycling_strategy_ = 0;
+ this->recycling_strategy_ = 0;
+
+ // Close down all cached service handlers.
+ CONNECTION_MAP_ENTRY *entry;
+ for (CONNECTION_MAP_ITERATOR iterator (connection_map_);
+ iterator.next (entry);
+ iterator.advance ())
+ {
+ entry->int_id_->recycler (0, 0);
+ entry->int_id_->close ();
+ }
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::open
+(ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Recycling_Strategy<SVC_HANDLER> *rec_s)
+{
+ // Initialize the creation strategy.
+
+ // First we decide if we need to clean up.
+ if (this->creation_strategy_ != 0 &&
+ this->delete_creation_strategy_ != 0 &&
+ cre_s != 0)
+ {
+ delete this->creation_strategy_;
+ this->creation_strategy_ = 0;
+ this->delete_creation_strategy_ = 0;
+ }
+
+ if (cre_s != 0)
+ this->creation_strategy_ = cre_s;
+ else if (this->creation_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->creation_strategy_,
+ CREATION_STRATEGY, -1);
+ this->delete_creation_strategy_ = 1;
+ }
+
+ // Initialize the concurrency strategy.
+
+ if (this->concurrency_strategy_ != 0 &&
+ this->delete_concurrency_strategy_ != 0 &&
+ con_s != 0)
+ {
+ delete this->concurrency_strategy_;
+ this->concurrency_strategy_ = 0;
+ this->delete_concurrency_strategy_ = 0;
+ }
+
+ if (con_s != 0)
+ this->concurrency_strategy_ = con_s;
+ else if (this->concurrency_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->concurrency_strategy_,
+ CONCURRENCY_STRATEGY, -1);
+ this->delete_concurrency_strategy_ = 1;
+ }
+
+ // Initialize the recycling strategy.
+
+ if (this->recycling_strategy_ != 0 &&
+ this->delete_recycling_strategy_ != 0 &&
+ rec_s != 0)
+ {
+ delete this->recycling_strategy_;
+ this->recycling_strategy_ = 0;
+ this->delete_recycling_strategy_ = 0;
+ }
+
+ if (rec_s != 0)
+ this->recycling_strategy_ = rec_s;
+ else if (this->recycling_strategy_ == 0)
+ {
+ ACE_NEW_RETURN (this->recycling_strategy_,
+ RECYCLING_STRATEGY, -1);
+ this->delete_recycling_strategy_ = 1;
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::check_hint_i
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry,
+ int &found)
+{
+ ACE_UNUSED_ARG (remote_addr);
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (local_addr);
+ ACE_UNUSED_ARG (reuse_addr);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (perms);
+
+ found = 0;
+
+ // Get the recycling act for the svc_handler
+ CONNECTION_MAP_ENTRY *possible_entry = (CONNECTION_MAP_ENTRY *) sh->recycling_act ();
+
+ // Check to see if the hint svc_handler has been closed down
+ if (possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED)
+ {
+ // If close, decrement refcount
+ if (possible_entry->ext_id_.decrement () == 0)
+ {
+ // If refcount goes to zero, close down the svc_handler
+ possible_entry->int_id_->recycler (0, 0);
+ possible_entry->int_id_->close ();
+ this->purge_i (possible_entry);
+ }
+
+ // Hint not successful
+ found = 0;
+
+ // Reset hint
+ sh = 0;
+ }
+
+ // If hint is not closed, see if it is connected to the correct
+ // address and is recyclable
+ else if ((possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
+ possible_entry->ext_id_.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE) &&
+ possible_entry->ext_id_.subject () == remote_addr)
+ {
+ // Hint successful
+ found = 1;
+
+ // Tell the <svc_handler> that it should prepare itself for
+ // being recycled.
+ this->prepare_for_recycling (sh);
+ }
+ else
+ {
+ // This hint will not be used.
+ possible_entry->ext_id_.decrement ();
+
+ // Hint not successful
+ found = 0;
+
+ // If <sh> is not connected to the correct address or is busy,
+ // we will not use it.
+ sh = 0;
+ }
+
+ if (found)
+ entry = possible_entry;
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::find_or_create_svc_handler_i
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry,
+ int &found)
+{
+ // Explicit type conversion
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);
+
+ // Try to find the address in the cache. Only if we don't find it
+ // do we create a new <SVC_HANDLER> and connect it with the server.
+ if (this->find (search_addr, entry) == -1)
+ {
+ // Set the flag
+ found = 0;
+
+ // We need to use a temporary variable here since we are not
+ // allowed to change <sh> because other threads may use this
+ // when we let go of the lock during the OS level connect.
+ //
+ // Note that making a new svc_handler, connecting remotely,
+ // binding to the map, and assigning of the hint and recycler
+ // should be atomic to the outside world.
+ SVC_HANDLER *potential_handler = 0;
+
+ // Create a new svc_handler
+ if (this->make_svc_handler (potential_handler) == -1)
+ return -1;
+
+ // Actively establish the connection. This is a timed blocking
+ // connect.
+ if (this->new_connection (potential_handler,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms) == -1)
+ {
+ // If connect() failed because of timeouts, we have to
+ // reject the connection entirely. This is necessary since
+ // currently there is no way for the non-blocking connects
+ // to complete and for the <Connector> to notify the cache
+ // of the completion of connect().
+ if (errno == EWOULDBLOCK)
+ errno = ENOTSUP;
+
+ // Close the svc handler.
+ potential_handler->close (0);
+
+ return -1;
+ }
+ else
+ {
+ // Insert the new SVC_HANDLER instance into the cache.
+ if (this->connection_map_.bind (search_addr,
+ potential_handler,
+ entry) == -1)
+ {
+ // Close the svc handler.
+ potential_handler->close (0);
+
+ return -1;
+ }
+
+ // Everything succeeded as planned. Assign <sh> to <potential_handler>.
+ sh = potential_handler;
+
+ // Set the recycler and the recycling act
+ this->assign_recycler (sh, this, entry);
+ }
+ }
+ else
+ // We found a cached svc_handler.
+ {
+ // Set the flag
+ found = 1;
+
+ // Get the cached <svc_handler>
+ sh = entry->int_id_;
+
+ // Tell the <svc_handler> that it should prepare itself for
+ // being recycled.
+ this->prepare_for_recycling (sh);
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::new_connection
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ // Yow, Reverse Guard! Let go of the lock for the duration of the
+ // actual connect. This will allow other threads to hack on the
+ // connection cache while this thread creates the new connection.
+ ACE_GUARD_RETURN (REVERSE_MUTEX, ace_mon, *this->reverse_lock_, -1);
+
+ return this->CONNECT_STRATEGY::connect_svc_handler (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::connect_svc_handler
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ int found = 0;
+
+ // This artificial scope is required since we need to let go of the
+ // lock *before* registering the newly created handler with the
+ // Reactor.
+ {
+ // Synchronization is required here as the setting of the
+ // recyclable state must be done atomically with the finding and
+ // binding of the service handler in the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ int result = this->connect_svc_handler_i (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms,
+ found);
+ if (result != 0)
+ return result;
+
+ }
+
+ // If it is a new connection, activate it.
+ //
+ // Note: This activation is outside the scope of the lock of the
+ // cached connector. This is necessary to avoid subtle deadlock
+ // conditions with this lock and the Reactor lock.
+
+ if (!found)
+ {
+ if (this->activate_svc_handler (sh) == -1)
+ {
+ // If an error occurs while activating the handler, the
+ // <activate_svc_handler> method will close the handler.
+ // This in turn will remove this entry from the internal
+ // table.
+
+ // Synchronization is required here as the setting of the
+ // handler to zero must be done atomically with the users of
+ // the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ // Reset handler.
+ sh = 0;
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::connect_svc_handler
+(SVC_HANDLER *&sh,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ int found = 0;
+
+ // This artificial scope is required since we need to let go of the
+ // lock *before* registering the newly created handler with the
+ // Reactor.
+ {
+ // Synchronization is required here as the setting of the
+ // recyclable state must be done atomically with the finding and
+ // binding of the service handler in the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ int result = this->connect_svc_handler_i (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms,
+ found);
+ sh_copy = sh;
+
+ if (result != 0)
+ return result;
+
+ }
+
+ // If it is a new connection, activate it.
+ //
+ // Note: This activation is outside the scope of the lock of the
+ // cached connector. This is necessary to avoid subtle deadlock
+ // conditions with this lock and the Reactor lock.
+
+ if (!found)
+ {
+ if (this->activate_svc_handler (sh_copy) == -1)
+ {
+ // If an error occurs while activating the handler, the
+ // <activate_svc_handler> method will close the handler.
+ // This in turn will remove this entry from the internal
+ // table.
+
+ // Synchronization is required here as the setting of the
+ // handler to zero must be done atomically with the users of
+ // the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ // Reset handler.
+ sh = 0;
+ sh_copy = 0;
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::connect_svc_handler_i
+(SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int& found)
+{
+ CONNECTION_MAP_ENTRY *entry = 0;
+
+ // Check if the user passed a hint svc_handler
+ if (sh != 0)
+ {
+ int result = this->check_hint_i (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms,
+ entry,
+ found);
+ if (result != 0)
+ return result;
+ }
+
+ // If not found
+ if (!found)
+ {
+ int result = this->find_or_create_svc_handler_i (sh,
+ remote_addr,
+ timeout,
+ local_addr,
+ reuse_addr,
+ flags,
+ perms,
+ entry,
+ found);
+ if (result != 0)
+ return result;
+ }
+
+ // For all successful cases: mark the <svc_handler> in the cache
+ // as being <in_use>. Therefore recyclable is BUSY.
+ entry->ext_id_.recycle_state (ACE_RECYCLABLE_BUSY);
+
+ // And increment the refcount
+ entry->ext_id_.increment ();
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::cache (const void *recycling_act)
+{
+ // Synchronization is required here as the setting of the recyclable
+ // state must be done atomically with respect to other threads that
+ // are querying the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ return this->cache_i (recycling_act);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::cache_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ // Mark the <svc_handler> in the cache as not being <in_use>.
+ // Therefore recyclable is IDLE.
+ entry->ext_id_.recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE);
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::recycle_state (const void *recycling_act,
+ ACE_Recyclable_State new_state)
+{
+ // Synchronization is required here as the setting of the recyclable
+ // state must be done atomically with respect to other threads that
+ // are querying the cache.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ return this->recycle_state_i (recycling_act,
+ new_state);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::recycle_state_i (const void *recycling_act,
+ ACE_Recyclable_State new_state)
+{
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ // Mark the <svc_handler> in the cache as not being <in_use>.
+ // Therefore recyclable is IDLE.
+ entry->ext_id_.recycle_state (new_state);
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ACE_Recyclable_State
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::recycle_state (const void *recycling_act) const
+{
+ // Const cast.
+ SELF *fake_this = ACE_const_cast (SELF *, this);
+
+ // Synchronization is required here.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *fake_this->lock_, ACE_RECYCLABLE_UNKNOWN);
+
+ return this->recycle_state_i (recycling_act);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ACE_Recyclable_State
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::recycle_state_i (const void *recycling_act) const
+{
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ // Mark the <svc_handler> in the cache as not being <in_use>.
+ // Therefore recyclable is IDLE.
+ return entry->ext_id_.recycle_state ();
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::purge (const void *recycling_act)
+{
+ // Excluded other threads from changing cache while we take this
+ // entry out.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ return this->purge_i (recycling_act);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::purge_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ return this->connection_map_.unbind (entry);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::mark_as_closed (const void *recycling_act)
+{
+ // Excluded other threads from changing cache while we take this
+ // entry out.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ return this->mark_as_closed_i (recycling_act);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::mark_as_closed_i (const void *recycling_act)
+{
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ // Mark the <svc_handler> in the cache as CLOSED.
+ entry->ext_id_.recycle_state (ACE_RECYCLABLE_CLOSED);
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::cleanup_hint (const void *recycling_act,
+ void **act_holder)
+{
+ // Excluded other threads from changing cache while we take this
+ // entry out.
+ ACE_GUARD_RETURN (MUTEX, ace_mon, *this->lock_, -1);
+
+ return this->cleanup_hint_i (recycling_act,
+ act_holder);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::cleanup_hint_i (const void *recycling_act,
+ void **act_holder)
+{
+ // Reset the <*act_holder> in the confines and protection of the
+ // lock.
+ if (act_holder)
+ *act_holder = 0;
+
+ // The wonders and perils of ACT
+ CONNECTION_MAP_ENTRY *entry = (CONNECTION_MAP_ENTRY *) recycling_act;
+
+ // Decrement the refcount on the <svc_handler>.
+ int refcount = entry->ext_id_.decrement ();
+
+ // If the svc_handler state is closed and the refcount == 0, call
+ // close() on svc_handler.
+ if (entry->ext_id_.recycle_state () == ACE_RECYCLABLE_CLOSED &&
+ refcount == 0)
+ {
+ entry->int_id_->recycler (0, 0);
+ entry->int_id_->close ();
+ this->purge_i (entry);
+ }
+
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ACE_Creation_Strategy<SVC_HANDLER> *
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::creation_strategy (void) const
+{
+ return this->creation_strategy_;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ACE_Recycling_Strategy<SVC_HANDLER> *
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::recycling_strategy (void) const
+{
+ return this->recycling_strategy_;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ACE_Concurrency_Strategy<SVC_HANDLER> *
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::concurrency_strategy (void) const
+{
+ return this->concurrency_strategy_;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::find (ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR> &search_addr,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry)
+{
+ typedef ACE_Hash_Map_Bucket_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,
+ SVC_HANDLER *,
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,
+ ACE_Null_Mutex>
+ CONNECTION_MAP_BUCKET_ITERATOR;
+
+ CONNECTION_MAP_BUCKET_ITERATOR iterator (this->connection_map_,
+ search_addr);
+
+ CONNECTION_MAP_BUCKET_ITERATOR end (this->connection_map_,
+ search_addr,
+ 1);
+
+ for (;
+ iterator != end;
+ ++iterator)
+ {
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS &addr = (*iterator).ext_id_;
+
+ if (addr.recycle_state () != ACE_RECYCLABLE_IDLE_AND_PURGABLE &&
+ addr.recycle_state () != ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE)
+ continue;
+
+ if (addr.subject () != search_addr.subject ())
+ continue;
+
+ entry = &(*iterator);
+ return 0;
+ }
+
+ return -1;
+}
+
+template <class SVC_HANDLER> void
+ACE_DLL_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Concurrency_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Reactive_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Thread_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Process_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Scheduling_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class SVC_HANDLER> void
+ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::dump");
+
+ ACE_Scheduling_Strategy<SVC_HANDLER>::dump ();
+}
+
+template <class SVC_HANDLER> void
+ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::dump");
+
+ ACE_Scheduling_Strategy<SVC_HANDLER>::dump ();
+}
+
+template <class SVC_HANDLER> ACE_INLINE void
+ACE_Singleton_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::dump");
+}
+
+template <class SVC_HANDLER> void
+ACE_Creation_Strategy<SVC_HANDLER>::dump (void) const
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::dump");
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Creation_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Singleton_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_DLL_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Concurrency_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Connect_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Process_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Accept_Strategy)
+ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Strategy)
+
+#endif /* ACE_STRATEGIES_T_C */
diff --git a/ace/Connection/Strategies_T.h b/ace/Connection/Strategies_T.h
new file mode 100644
index 00000000000..4c9c327cffa
--- /dev/null
+++ b/ace/Connection/Strategies_T.h
@@ -0,0 +1,971 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Strategies_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_STRATEGIES_T_H
+#define ACE_STRATEGIES_T_H
+#include "ace/pre.h"
+
+#include "ace/Hash_Map_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Synch_Options.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Connection_Recycling_Strategy.h"
+#include "ace/Refcountable.h"
+#include "ace/Hashable.h"
+#include "ace/Recyclable.h"
+
+// Needed for broken linkers that can't grok long symbols.
+#define ACE_Refcounted_Hash_Recyclable ARHR
+
+/**
+ * @class ACE_Recycling_Strategy
+ *
+ * @brief Defines the interface (and default implementation) for
+ * specifying a recycling strategy for a SVC_HANDLER.
+ *
+ * Acts as a consular to the Svc_Handler, preparing it for the
+ * tough times ahead when the Svc_Handler will be recycled.
+ */
+template<class SVC_HANDLER>
+class ACE_Recycling_Strategy
+{
+public:
+ /// Virtual Destructor
+ virtual ~ACE_Recycling_Strategy (void);
+
+ /// Tell the Svc_Handler something about the recycler, so that it can
+ /// reach the recycler when necessary.
+ virtual int assign_recycler (SVC_HANDLER *svc_handler,
+ ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act);
+
+ /// This allows us to prepare the svc_handler for recycling.
+ virtual int prepare_for_recycling (SVC_HANDLER *svc_handler);
+};
+
+/**
+ * @class ACE_Creation_Strategy
+ *
+ * @brief Defines the interface for specifying a creation strategy for
+ * a SVC_HANDLER.
+ *
+ * The default behavior is to make a new SVC_HANDLER. However,
+ * subclasses can override this strategy to perform SVC_HANDLER
+ * creation in any way that they like (such as creating subclass
+ * instances of SVC_HANDLER, using a singleton, dynamically
+ * linking the handler, etc.).
+ */
+template <class SVC_HANDLER>
+class ACE_Creation_Strategy
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Default constructor.
+ ACE_Creation_Strategy (ACE_Thread_Manager * = 0);
+
+ /// A <Thread_Manager> is useful when creating active objects.
+ int open (ACE_Thread_Manager * = 0);
+
+ virtual ~ACE_Creation_Strategy (void);
+
+ // = Factory method.
+ /**
+ * Create a SVC_HANDLER with the appropriate creation strategy. The
+ * default behavior of this method is to make a new <SVC_HANDLER> if
+ * <sh> == 0 (passing in the <Thread_Manager>), else <sh> is
+ * unchanged. Returns -1 on failure, else 0.
+ */
+ virtual int make_svc_handler (SVC_HANDLER *&sh);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Pointer to a thread manager.
+ ACE_Thread_Manager *thr_mgr_;
+};
+
+/**
+ * @class ACE_Singleton_Strategy
+ *
+ * @brief Defines the interface for specifying a creation strategy for
+ * a <SVC_HANDLER> that always returns the same <SVC_HANDLER> (i.e.,
+ * it's a Singleton).
+ *
+ * Note that this class takes over the ownership of the
+ * SVC_HANDLER passed into it as a parameter and it becomes
+ * responsible for deleting this object.
+ */
+template <class SVC_HANDLER>
+class ACE_Singleton_Strategy : public ACE_Creation_Strategy<SVC_HANDLER>
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Singleton_Strategy (SVC_HANDLER * = 0,
+ ACE_Thread_Manager * = 0);
+ int open (SVC_HANDLER *,
+ ACE_Thread_Manager * = 0);
+ virtual ~ACE_Singleton_Strategy (void);
+
+ // = Factory method.
+ /// Create a Singleton SVC_HANDLER by always returning the same
+ /// SVC_HANDLER. Returns -1 on failure, else 0.
+ virtual int make_svc_handler (SVC_HANDLER *&);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Pointer to the Singleton svc_handler.
+ SVC_HANDLER *svc_handler_;
+
+ /// Keep track of whether we need to delete the <SVC_HANDLER>.
+ int delete_svc_handler_;
+};
+
+/**
+ * @class ACE_DLL_Strategy
+ *
+ * @brief Defines the interface for specifying a creation strategy for
+ * a SVC_HANDLER based on dynamic linking of the SVC_HANDLER.
+ */
+template <class SVC_HANDLER>
+class ACE_DLL_Strategy : public ACE_Creation_Strategy<SVC_HANDLER>
+{
+public:
+ // = Intialization and termination methods.
+
+ /// "Do-nothing" constructor.
+ ACE_DLL_Strategy (void);
+
+ /// Initialize the DLL strategy based upon the service's DLL
+ /// information contained in the <svc_dll_info> string.
+ ACE_DLL_Strategy (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
+ ACE_Service_Repository *,
+ ACE_Thread_Manager * = 0);
+
+ /// Initialize the DLL strategy based upon the service's DLL
+ /// information contained in the <svc_dll_info> string.
+ int open (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
+ ACE_Service_Repository *,
+ ACE_Thread_Manager * = 0);
+
+ // = Factory method.
+ /// Create a SVC_HANDLER by dynamically linking it from a DLL.
+ /// Returns -1 on failure, else 0.
+ virtual int make_svc_handler (SVC_HANDLER *&);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ typedef ACE_Creation_Strategy<SVC_HANDLER> inherited;
+
+ /// Name of the DLL to dynamically link.
+ char dll_name_[MAXPATHLEN + 1];
+
+ /// Name of the factory function in the shared library to use to
+ /// obtain a pointer to the new SVC_HANDLER.
+ char factory_function_[MAXPATHLEN + 1];
+
+ /// Name of the service.
+ char svc_name_[MAXNAMELEN + 1];
+
+ /// Pointer to the <Service_Repository>.
+ ACE_Service_Repository *svc_rep_;
+};
+
+/**
+ * @class ACE_Concurrency_Strategy
+ *
+ * @brief Defines the interface for specifying a concurrency strategy
+ * for a SVC_HANDLER.
+ *
+ * Default behavior is to activate the SVC_HANDLER by calling
+ * its <open> method (which allows the SVC_HANDLER to define its
+ * own concurrency strategy). However, subclasses can override
+ * this default strategy to do more sophisticated concurrency
+ * activations (such as creating the SVC_HANDLER as an active
+ * object via multi-threading or multi-processing).
+ */
+template <class SVC_HANDLER>
+class ACE_Concurrency_Strategy
+{
+public:
+ /// Constructor
+ ACE_Concurrency_Strategy (int flags = 0);
+
+ // = Factory method.
+ /**
+ * Activate the <svc_handler> with an appropriate concurrency
+ * strategy. The default behavior of this method is to activate the
+ * SVC_HANDLER by calling its <open> method (which allows the
+ * SVC_HANDLER to define its own concurrency strategy).
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg = 0);
+
+ virtual ~ACE_Concurrency_Strategy (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+
+ /// Flags that are parsed to set options for the connected
+ /// <SVC_HANDLER>.
+ int flags_;
+};
+
+/**
+ * @class ACE_Reactive_Strategy
+ *
+ * @brief Defines the interface for specifying a Reactive concurrency
+ * strategy for a SVC_HANDLER.
+ *
+ * This class provides a strategy that registers the
+ * <SVC_HANDLER> with a <Reactor>.
+ */
+template <class SVC_HANDLER>
+class ACE_Reactive_Strategy : public ACE_Concurrency_Strategy <SVC_HANDLER>
+{
+public:
+ // = Intialization and termination methods.
+ /// "Do-nothing constructor"
+ ACE_Reactive_Strategy (int flags = 0);
+
+ /// Initialize the strategy.
+ ACE_Reactive_Strategy (ACE_Reactor *reactor,
+ ACE_Reactor_Mask = ACE_Event_Handler::READ_MASK,
+ int flags = 0);
+
+ /// Initialize the strategy.
+ virtual int open (ACE_Reactor *reactor,
+ ACE_Reactor_Mask = ACE_Event_Handler::READ_MASK,
+ int flags = 0);
+
+ /// Destructor.
+ virtual ~ACE_Reactive_Strategy (void);
+
+ // = Factory method.
+ /// Activate the <svc_handler> by registering it with the <Reactor>
+ /// and then calling it's <open> hook.
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> inherited;
+
+ /// Pointer to the Reactor we'll use to register the <SVC_HANDLER>.
+ ACE_Reactor *reactor_;
+
+ /// The mask that we pass to the <Reactor> when we register the
+ /// <SVC_HANDLER>.
+ ACE_Reactor_Mask mask_;
+};
+
+/**
+ * @class ACE_Thread_Strategy
+ *
+ * @brief Defines the interface for specifying a concurrency strategy
+ * for a <SVC_HANDLER> based on multithreading.
+ *
+ * This class provides a strategy that manages the creation of
+ * threads to handle requests from clients concurrently. It
+ * behaves as a "thread factory", spawning threads "on-demand"
+ * to run the service specified by a user-supplied
+ * <SVC_HANDLER>.
+ */
+template <class SVC_HANDLER>
+class ACE_Thread_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER>
+{
+public:
+ // = Intialization and termination methods.
+ /// "Do-nothing constructor"
+ ACE_Thread_Strategy (int flags = 0);
+
+ /// Initialize the strategy.
+ ACE_Thread_Strategy (ACE_Thread_Manager *tm,
+ long thr_flags,
+ size_t n_threads = 1,
+ int flags = 0);
+
+ /// Initialize the strategy.
+ virtual int open (ACE_Thread_Manager *tm,
+ long thr_flags,
+ size_t n_threads = 1,
+ int flags = 0);
+
+ virtual ~ACE_Thread_Strategy (void);
+
+ // = Factory method.
+ /**
+ * Activate the <svc_handler> with an appropriate concurrency
+ * strategy. This method activates the SVC_HANDLER by first calling
+ * its <open> method and then calling its <activate> method to turn
+ * it into an active object.
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> inherited;
+
+ /// Thread manager for this class (must be provided).
+ ACE_Thread_Manager *thr_mgr_;
+
+ /// Flags to pass into the <SVC_HANDLER::activate> method.
+ long thr_flags_;
+
+ /// Number of threads to spawn.
+ size_t n_threads_;
+};
+
+/**
+ * @class ACE_Process_Strategy
+ *
+ * @brief Defines the interface for specifying a concurrency strategy
+ * for a <SVC_HANDLER> based on multiprocessing.
+ *
+ * This class provides a strategy that manages the creation of
+ * processes to handle requests from clients concurrently. It
+ * behaves as a "process factory", using <ACE::fork> to fork
+ * threads "on-demand" to run the service specified by a
+ * user-supplied <SVC_HANDLER> in a separate process.
+ */
+template <class SVC_HANDLER>
+class ACE_Process_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER>
+{
+public:
+ // = Intialization and termination methods.
+
+ /// Initialize the strategy. If <avoid_zombies> is non-0 then set a
+ /// flag to <ACE::fork> to avoid zombies.
+ ACE_Process_Strategy (size_t n_processes = 1,
+ ACE_Event_Handler *acceptor = 0,
+ ACE_Reactor * = 0,
+ int avoid_zombies = 0);
+
+ /// Initialize the strategy. If <avoid_zombies> is non-0 then set a
+ /// flag to <ACE::fork> to avoid zombies.
+ virtual int open (size_t n_processes = 1,
+ ACE_Event_Handler *acceptor = 0,
+ ACE_Reactor * = 0,
+ int avoid_zombies = 0);
+
+ virtual ~ACE_Process_Strategy (void);
+
+ // = Factory method.
+ /**
+ * Activate the <svc_handler> with an appropriate concurrency
+ * strategy. This method activates the SVC_HANDLER by first forking
+ * and then calling the <open> method of the SVC_HANDLER in the
+ * child.
+ */
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER> inherited;
+
+ /// Number of processes to spawn.
+ size_t n_processes_;
+
+ /**
+ * This is the <Acceptor> in the parent is listening on. We need to
+ * make sure that we remove it from the Reactor and close it down in
+ * the child.
+ */
+ ACE_Event_Handler *acceptor_;
+
+ /**
+ * This is the <Reactor> the child is using in conjunction with the
+ * <Acceptor>. We need to remove the <Acceptor> from this <Reactor>
+ * in the child.
+ */
+ ACE_Reactor *reactor_;
+};
+
+/**
+ * @class ACE_Accept_Strategy
+ *
+ * @brief Defines the interface for specifying a passive connection
+ * acceptance strategy for a SVC_HANDLER.
+ *
+ * This class provides a strategy that manages passive
+ * connection acceptance of a client.
+ */
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class ACE_Accept_Strategy
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Accept_Strategy (ACE_Reactor *reactor = ACE_Reactor::instance ());
+
+ /// Initialize the <peer_acceptor_> with <local_addr>.
+ ACE_Accept_Strategy (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ int restart = 0,
+ ACE_Reactor *reactor = ACE_Reactor::instance ());
+
+ /// Initialize the <peer_acceptor_> with <local_addr>, indicating
+ /// whether to <reuse_addr> if it's already in use.
+ virtual int open (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
+ int reuse_addr = 0);
+
+ /// Return the underlying ACE_HANDLE of the <peer_acceptor_>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Return a reference to the <peer_acceptor_>.
+ virtual ACE_PEER_ACCEPTOR &acceptor (void) const;
+
+ virtual ~ACE_Accept_Strategy (void);
+
+ // = Factory method.
+ /// The default behavior delegates to the <accept> method of the
+ /// PEER_ACCEPTOR.
+ virtual int accept_svc_handler (SVC_HANDLER *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Factory that establishes connections passively.
+ ACE_PEER_ACCEPTOR peer_acceptor_;
+
+ /// Pointer to the reactor used by the Acceptor.
+ ACE_Reactor *reactor_;
+
+ /// Needed to reopen the socket if <accept> fails.
+ int reuse_addr_;
+
+ /// Needed to reopen the socket if <accept> fails.
+ ACE_PEER_ACCEPTOR_ADDR peer_acceptor_addr_;
+};
+
+/**
+ * @class ACE_Connect_Strategy
+ *
+ * @brief Defines the interface for specifying an active
+ * connection establishment strategy for a SVC_HANDLER.
+ *
+ * This class provides a strategy that manages active
+ * connection establishment to a server.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_Connect_Strategy
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Connect_Strategy (void);
+
+ /// Return a reference to the <peer_connector_>.
+ virtual ACE_PEER_CONNECTOR &connector (void) const;
+
+ virtual ~ACE_Connect_Strategy (void);
+
+ // = Factory method.
+ /// The default behavior delegates to the <connect> method of the
+ /// <PEER_CONNECTOR::connect>.
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /**
+ * The default behavior delegates to the <connect> method of the
+ * <PEER_CONNECTOR::connect>.
+ * Please check the documentation in Connector.h for more details.
+ */
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Factory that establishes connections actively.
+ ACE_PEER_CONNECTOR connector_;
+};
+
+/**
+ * @class ACE_Scheduling_Strategy
+ *
+ * @brief Defines the interface for specifying how to suspend and
+ * resume a service .
+ *
+ * This class provides a strategy that allows arbitrarily
+ * sophisticated service suspension and resumption. The default
+ * behavior is to do nothing...
+ */
+template <class SVC_HANDLER>
+class ACE_Scheduling_Strategy
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Constructor
+ ACE_Scheduling_Strategy (SVC_HANDLER * = 0);
+
+ /// Destructor
+ virtual ~ACE_Scheduling_Strategy (void);
+
+ // = Scheduling methods
+
+ /// Suspend hook.
+ virtual int suspend (void);
+
+ /// Resume hook.
+ virtual int resume (void);
+
+ /// Dump the state of the object.
+ virtual void dump (void) const;
+};
+
+/**
+ * @class ACE_Schedule_All_Reactive_Strategy
+ *
+ * @brief Defines the interface for specifying how to suspend and
+ * resume a single-threaded reactive service .
+ *
+ * This class provides a strategy that suspends and resumes all
+ * the Event_Handlers in a Reactor in one fell swoop.
+ */
+template <class SVC_HANDLER>
+class ACE_Schedule_All_Reactive_Strategy : public ACE_Scheduling_Strategy<SVC_HANDLER>
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor
+ ACE_Schedule_All_Reactive_Strategy (SVC_HANDLER * = 0);
+
+ // = Scheduling methods
+
+ /// Suspend hook.
+ virtual int suspend (void);
+
+ /// Resume hook.
+ virtual int resume (void);
+
+ /// Dump the state of the object.
+ virtual void dump (void) const;
+
+protected:
+
+ /// Thread Manager
+ ACE_Reactor *reactor_;
+};
+
+/**
+ * @class ACE_Schedule_All_Threaded_Strategy
+ *
+ * @brief Defines the interface for specifying how to suspend and
+ * resume a multithreaded service .
+ *
+ * This class provides a strategy that suspends and resumes all
+ * the Event_Handlers controlled by a Thread_Manager in one fell swoop.
+ */
+template <class SVC_HANDLER>
+class ACE_Schedule_All_Threaded_Strategy : public ACE_Scheduling_Strategy<SVC_HANDLER>
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor
+ ACE_Schedule_All_Threaded_Strategy (SVC_HANDLER * = 0);
+
+ // = Scheduling methods
+
+ /// Suspend hook.
+ virtual int suspend (void);
+
+ /// Resume hook.
+ virtual int resume (void);
+
+ /// Dump the state of the object.
+ virtual void dump (void) const;
+
+protected:
+
+ /// Thread Manager
+ ACE_Thread_Manager *thr_mgr_;
+};
+
+/**
+ * @class ACE_NOOP_Creation_Strategy
+ *
+ * @brief Implements a no-op creation strategy in order to defer
+ * decisions regarding creation to some later point in time, such
+ * as in connect or accept strategy.
+ *
+ * An example of the use of this is in the
+ * <ACE_Cached_Connect_Strategy>, which only returns a single
+ * connection for a given endpoint.
+ */
+template <class SVC_HANDLER>
+class ACE_NOOP_Creation_Strategy : public ACE_Creation_Strategy<SVC_HANDLER>
+{
+public:
+ /// This is a no-op.
+ virtual int make_svc_handler (SVC_HANDLER *&);
+};
+
+/**
+ * @class ACE_NOOP_Concurrency_Strategy
+ *
+ * @brief Implements a no-op activation strategy in order to avoid
+ * calling open on a svc_handler multiple times.
+ *
+ * An example of the use of this is in the
+ * <ACE_Cached_Connect_Strategy>, which reuses svc_handlers.
+ * Therefore we don't want to call open on the recycled
+ * svc_handler more than once.
+ */
+template <class SVC_HANDLER>
+class ACE_NOOP_Concurrency_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER>
+{
+public:
+ // = Factory method.
+ /// This is a no-op.
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler,
+ void *arg = 0);
+};
+
+template <class T>
+class ACE_Refcounted_Hash_Recyclable : public ACE_Refcountable,
+ public ACE_Hashable,
+ public ACE_Recyclable
+{
+public:
+ /// Default constructor.
+ ACE_Refcounted_Hash_Recyclable (void);
+
+ /// Constructor.
+ ACE_Refcounted_Hash_Recyclable (const T &t,
+ int refcount = 0,
+ ACE_Recyclable_State state = ACE_RECYCLABLE_UNKNOWN);
+
+ /// Destructor
+ virtual ~ACE_Refcounted_Hash_Recyclable (void);
+
+ /// Compares two instances.
+ int operator== (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const;
+ int operator!= (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const;
+
+ T &subject ();
+
+protected:
+ /// Computes and returns hash value.
+ u_long hash_i (void) const;
+
+ T t_;
+};
+
+/**
+ * @class ACE_Cached_Connect_Strategy
+ *
+ * @brief A connection strategy which caches connections to peers
+ * (represented by <SVC_HANDLER> instances), thereby allowing
+ * subsequent re-use of unused, but available, connections.
+ *
+ * <ACE_Cached_Connect_Strategy> is intended to be used as a
+ * plug-in connection strategy for <ACE_Strategy_Connector>.
+ * It's added value is re-use of established connections.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX>
+class ACE_Cached_Connect_Strategy : public ACE_Connection_Recycling_Strategy, public ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+{
+public:
+
+ typedef ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX> SELF;
+
+ /// Constructor
+ ACE_Cached_Connect_Strategy (ACE_Creation_Strategy<SVC_HANDLER> *cre_s = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s = 0,
+ ACE_Recycling_Strategy<SVC_HANDLER> *rec_s = 0,
+ MUTEX *mutex = 0,
+ int delete_mutex = 0);
+
+ /// Destructor
+ virtual ~ACE_Cached_Connect_Strategy (void);
+
+ /// This methods allow you to change the strategies used by the
+ /// cached connector.
+ virtual int open (ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ ACE_Recycling_Strategy<SVC_HANDLER> *rec_s);
+
+ /// Template method for making a new <svc_handler>
+ virtual int make_svc_handler (SVC_HANDLER *&sh);
+
+ /// Template method for activating a new <svc_handler>
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler);
+
+ /// Template method for setting the recycler information of the
+ /// svc_handler.
+ virtual int assign_recycler (SVC_HANDLER *svc_handler,
+ ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act);
+
+ /// Template method for preparing the svc_handler for recycling.
+ virtual int prepare_for_recycling (SVC_HANDLER *svc_handler);
+
+ /**
+ * Checks to see if there is already a <SVC_HANDLER> in the cache
+ * connected to the <remote_addr>. If so, we return this pointer.
+ * Otherwise we establish the connection, put it into the cache, and
+ * return the <SVC_HANDLER> pointer. <[NOTE]>: the <{reuse_addr}>
+ * argument does NOT control re-use of addresses in the cache.
+ * Rather, if the underlying protocol requires a "dead time" prior
+ * to re-use of its addresses (TCP is a classic example of this),
+ * <{and}> the protocol provides a means by which to defeat the dead
+ * time, setting this argument to non-zero will defeat the dead-time
+ * requirement. <{Dev. Note: We might want to consider enhancing
+ * the interface at some point so that this also controls re-use of
+ * the cache.}>
+ */
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+ virtual int connect_svc_handler (SVC_HANDLER *&sh,
+ SVC_HANDLER *&sh_copy,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /// Remove from cache.
+ virtual int purge (const void *recycling_act);
+
+ /// Add to cache.
+ virtual int cache (const void *recycling_act);
+
+ /// Get/Set <recycle_state>.
+ virtual int recycle_state (const void *recycling_act,
+ ACE_Recyclable_State new_state);
+ virtual ACE_Recyclable_State recycle_state (const void *recycling_act) const;
+
+ /// Mark as closed.
+ virtual int mark_as_closed (const void *recycling_act);
+
+ /**
+ * Mark as closed (non-locking version). This method needs to be public
+ * as it is used in the cleanup of handlers where teh locked version causes
+ * a deadlock.
+ */
+ virtual int mark_as_closed_i (const void *recycling_act);
+
+ /// Cleanup hint and reset <*act_holder> to zero if <act_holder != 0>.
+ virtual int cleanup_hint (const void *recycling_act,
+ void **act_holder = 0);
+
+ // = Define some useful typedefs.
+ typedef ACE_Creation_Strategy<SVC_HANDLER>
+ CREATION_STRATEGY;
+ typedef ACE_Concurrency_Strategy<SVC_HANDLER>
+ CONCURRENCY_STRATEGY;
+ typedef ACE_Recycling_Strategy<SVC_HANDLER>
+ RECYCLING_STRATEGY;
+
+ // = Super class
+ typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ CONNECT_STRATEGY;
+
+ // = Typedefs for managing the map
+ typedef ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS;
+ typedef ACE_Hash_Map_Manager<REFCOUNTED_HASH_RECYCLABLE_ADDRESS, SVC_HANDLER *, ACE_Null_Mutex>
+ CONNECTION_MAP;
+ typedef ACE_Hash_Map_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDRESS, SVC_HANDLER *, ACE_Null_Mutex>
+ CONNECTION_MAP_ITERATOR;
+ typedef ACE_Hash_Map_Entry<REFCOUNTED_HASH_RECYCLABLE_ADDRESS, SVC_HANDLER *>
+ CONNECTION_MAP_ENTRY;
+
+ typedef ACE_Reverse_Lock<MUTEX> REVERSE_MUTEX;
+
+ // = Strategy accessors
+ virtual ACE_Creation_Strategy<SVC_HANDLER> *creation_strategy (void) const;
+ virtual ACE_Recycling_Strategy<SVC_HANDLER> *recycling_strategy (void) const;
+ virtual ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy (void) const;
+
+protected:
+
+ /// Creates a new connection.
+ virtual int new_connection (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms);
+
+ /// Find an idle handle.
+ int find (ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR> &search_addr,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry);
+
+ /// Remove from cache (non-locking version).
+ virtual int purge_i (const void *recycling_act);
+
+ /// Add to cache (non-locking version).
+ virtual int cache_i (const void *recycling_act);
+
+ /// Get/Set <recycle_state> (non-locking version).
+ virtual int recycle_state_i (const void *recycling_act,
+ ACE_Recyclable_State new_state);
+ virtual ACE_Recyclable_State recycle_state_i (const void *recycling_act) const;
+
+ /// Cleanup hint and reset <*act_holder> to zero if <act_holder != 0>.
+ virtual int cleanup_hint_i (const void *recycling_act,
+ void **act_holder);
+
+ // = Helpers
+ int check_hint_i (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry,
+ int &found);
+
+ int find_or_create_svc_handler_i (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, SVC_HANDLER *> *&entry,
+ int &found);
+
+ virtual int connect_svc_handler_i (SVC_HANDLER *&sh,
+ const ACE_PEER_CONNECTOR_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_PEER_CONNECTOR_ADDR &local_addr,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int &found);
+
+ /// Table that maintains the cache of connected <SVC_HANDLER>s.
+ CONNECTION_MAP connection_map_;
+
+ /// Mutual exclusion for this object.
+ MUTEX *lock_;
+
+ /// Mutual exclusion for this object.
+ int delete_lock_;
+
+ /// Reverse lock.
+ REVERSE_MUTEX *reverse_lock_;
+
+ // = Strategy objects.
+
+ /// Creation strategy for an <Connector>.
+ CREATION_STRATEGY *creation_strategy_;
+
+ /// 1 if <Connector> created the creation strategy and thus should
+ /// delete it, else 0.
+ int delete_creation_strategy_;
+
+ /// Concurrency strategy for an <Connector>.
+ CONCURRENCY_STRATEGY *concurrency_strategy_;
+
+ /// 1 if <Connector> created the concurrency strategy and thus should
+ /// delete it, else 0.
+ int delete_concurrency_strategy_;
+
+ /// Recycling strategy for an <Connector>.
+ RECYCLING_STRATEGY *recycling_strategy_;
+
+ /// 1 if <Connector> created the recycling strategy and thus should
+ /// delete it, else 0.
+ int delete_recycling_strategy_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/Strategies_T.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Strategies_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Strategies_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_STRATEGIES_T_H */
diff --git a/ace/Connection/Strategies_T.i b/ace/Connection/Strategies_T.i
new file mode 100644
index 00000000000..e6376aee006
--- /dev/null
+++ b/ace/Connection/Strategies_T.i
@@ -0,0 +1,439 @@
+/* -*- C++ -*- */
+// $Id$
+
+template<class SVC_HANDLER> ASYS_INLINE
+ACE_Recycling_Strategy<SVC_HANDLER>::~ACE_Recycling_Strategy (void)
+{
+}
+
+template<class SVC_HANDLER> ASYS_INLINE int
+ACE_Recycling_Strategy<SVC_HANDLER>::assign_recycler (SVC_HANDLER *svc_handler,
+ ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act)
+{
+ svc_handler->recycler (recycler, recycling_act);
+ return 0;
+}
+
+template<class SVC_HANDLER> ASYS_INLINE int
+ACE_Recycling_Strategy<SVC_HANDLER>::prepare_for_recycling (SVC_HANDLER *svc_handler)
+{
+ return svc_handler->recycle ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Singleton_Strategy<SVC_HANDLER>::ACE_Singleton_Strategy (SVC_HANDLER *sh,
+ ACE_Thread_Manager *tm)
+ : svc_handler_ (0),
+ delete_svc_handler_ (1)
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::ACE_Singleton_Strategy");
+ if (this->open (sh, tm) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Singleton_Strategy")));
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Singleton_Strategy<SVC_HANDLER>::~ACE_Singleton_Strategy (void)
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::~ACE_Singleton_Strategy");
+ if (this->delete_svc_handler_ != 0)
+ delete this->svc_handler_;
+}
+
+// Create a Singleton SVC_HANDLER by always returning the same
+// SVC_HANDLER.
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Singleton_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Singleton_Strategy<SVC_HANDLER>::make_svc_handler");
+ sh = this->svc_handler_;
+ return 0;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Creation_Strategy<SVC_HANDLER>::open (ACE_Thread_Manager *thr_mgr)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::open");
+ this->thr_mgr_ = thr_mgr;
+ return 0;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Creation_Strategy<SVC_HANDLER>::ACE_Creation_Strategy (ACE_Thread_Manager *thr_mgr)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::ACE_Creation_Strategy");
+ if (this->open (thr_mgr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Creation_Strategy")));
+}
+
+// Default behavior is to make a new SVC_HANDLER, passing in the
+// Thread_Manager (if any).
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Creation_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&sh)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::make_svc_handler");
+
+ if (sh == 0)
+ ACE_NEW_RETURN (sh, SVC_HANDLER (this->thr_mgr_), -1);
+ return 0;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Creation_Strategy<SVC_HANDLER>::~ACE_Creation_Strategy (void)
+{
+ ACE_TRACE ("ACE_Creation_Strategy<SVC_HANDLER>::~ACE_Creation_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
+ ACE_Service_Repository *svc_rep,
+ ACE_Thread_Manager *thr_mgr)
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy");
+ if (this->open (dll_name,
+ factory_function,
+ svc_name,
+ svc_rep,
+ thr_mgr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("open")));
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (void)
+{
+ ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Concurrency_Strategy<SVC_HANDLER>::ACE_Concurrency_Strategy (int flags)
+ : flags_ (flags)
+{
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::~ACE_Concurrency_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Concurrency_Strategy<SVC_HANDLER>::~ACE_Concurrency_Strategy (void)
+{
+ ACE_TRACE ("ACE_Concurrency_Strategy<SVC_HANDLER>::~ACE_Concurrency_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy (ACE_Reactor *reactor,
+ ACE_Reactor_Mask mask,
+ int flags)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy");
+
+ if (this->open (reactor,
+ mask,
+ flags) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy")));
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy (int flags)
+ : ACE_Concurrency_Strategy<SVC_HANDLER> (flags),
+ reactor_ (0),
+ mask_ (ACE_Event_Handler::NULL_MASK)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::ACE_Reactive_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Reactive_Strategy<SVC_HANDLER>::~ACE_Reactive_Strategy (void)
+{
+ ACE_TRACE ("ACE_Reactive_Strategy<SVC_HANDLER>::~ACE_Reactive_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy (ACE_Thread_Manager *thr_mgr,
+ long thr_flags,
+ size_t n_threads,
+ int flags)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy");
+
+ if (this->open (thr_mgr,
+ thr_flags,
+ n_threads,
+ flags) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy")));
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy (int flags)
+ : ACE_Concurrency_Strategy<SVC_HANDLER> (flags),
+ thr_mgr_ (0),
+ thr_flags_ (0),
+ n_threads_ (1)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::ACE_Thread_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Thread_Strategy<SVC_HANDLER>::~ACE_Thread_Strategy (void)
+{
+ ACE_TRACE ("ACE_Thread_Strategy<SVC_HANDLER>::~ACE_Thread_Strategy");
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ASYS_INLINE
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Accept_Strategy (ACE_Reactor *reactor)
+ : reactor_ (reactor)
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Accept_Strategy");
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ASYS_INLINE ACE_HANDLE
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
+ return this->peer_acceptor_.get_handle ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ASYS_INLINE ACE_PEER_ACCEPTOR &
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
+ return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ASYS_INLINE
+ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Accept_Strategy (void)
+{
+ ACE_TRACE ("ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Accept_Strategy");
+
+ // Close the underlying acceptor.
+ this->peer_acceptor_.close ();
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ASYS_INLINE ACE_PEER_CONNECTOR &
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector (void) const
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector");
+ return (ACE_PEER_CONNECTOR &) this->connector_;
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ASYS_INLINE
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connect_Strategy (void)
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connect_Strategy");
+}
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ASYS_INLINE
+ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connect_Strategy (void)
+{
+ ACE_TRACE ("ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connect_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Process_Strategy<SVC_HANDLER>::ACE_Process_Strategy (size_t n_processes,
+ ACE_Event_Handler *acceptor,
+ ACE_Reactor *reactor,
+ int avoid_zombies)
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::ACE_Process_Strategy");
+ if (this->open (n_processes,
+ acceptor,
+ reactor,
+ avoid_zombies) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Process_Strategy")));
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Process_Strategy<SVC_HANDLER>::~ACE_Process_Strategy (void)
+{
+ ACE_TRACE ("ACE_Process_Strategy<SVC_HANDLER>::~ACE_Process_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Scheduling_Strategy<SVC_HANDLER>::ACE_Scheduling_Strategy (SVC_HANDLER *)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::ACE_Scheduling_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Scheduling_Strategy<SVC_HANDLER>::~ACE_Scheduling_Strategy (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::~ACE_Scheduling_Strategy");
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Scheduling_Strategy<SVC_HANDLER>::suspend (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::suspend");
+ return -1;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Scheduling_Strategy<SVC_HANDLER>::resume (void)
+{
+ ACE_TRACE ("ACE_Scheduling_Strategy<SVC_HANDLER>::resume");
+ return -1;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::ACE_Schedule_All_Reactive_Strategy
+ (SVC_HANDLER *scheduler)
+ : ACE_Scheduling_Strategy<SVC_HANDLER> (scheduler)
+{
+ ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::ACE_Schedule_All_Reactive_Strategy");
+
+ if (scheduler == 0 || scheduler->reactor () == 0)
+ this->reactor_ = ACE_Reactor::instance ();
+ else
+ this->reactor_ = scheduler->reactor ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::suspend (void)
+{
+ ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::suspend");
+ return this->reactor_->suspend_handlers ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::resume (void)
+{
+ ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SVC_HANDLER>::resume");
+ return this->reactor_->resume_handlers ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE
+ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::ACE_Schedule_All_Threaded_Strategy
+ (SVC_HANDLER *scheduler)
+ : ACE_Scheduling_Strategy<SVC_HANDLER> (scheduler)
+{
+ ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::ACE_Schedule_All_Threaded_Strategy");
+
+ if (scheduler == 0 || scheduler->thr_mgr () == 0)
+ this->thr_mgr_ = ACE_Thread_Manager::instance ();
+ else
+ this->thr_mgr_ = scheduler->thr_mgr ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::suspend (void)
+{
+ ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::suspend");
+ return this->thr_mgr_->suspend_all ();
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::resume (void)
+{
+ ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SVC_HANDLER>::resume");
+ return this->thr_mgr_->resume_all ();
+}
+
+template <class T> ASYS_INLINE
+ACE_Refcounted_Hash_Recyclable<T>::ACE_Refcounted_Hash_Recyclable (void)
+ : ACE_Refcountable (0),
+ ACE_Hashable (),
+ ACE_Recyclable (ACE_RECYCLABLE_UNKNOWN),
+ t_ ()
+{
+}
+
+template <class T> ASYS_INLINE
+ACE_Refcounted_Hash_Recyclable<T>::ACE_Refcounted_Hash_Recyclable (const T &t,
+ int refcount,
+ ACE_Recyclable_State state)
+ : ACE_Refcountable (refcount),
+ ACE_Hashable (),
+ ACE_Recyclable (state),
+ t_ (t)
+{
+}
+
+template <class T> ASYS_INLINE
+ACE_Refcounted_Hash_Recyclable<T>::~ACE_Refcounted_Hash_Recyclable (void)
+{
+}
+
+template <class T> ASYS_INLINE u_long
+ACE_Refcounted_Hash_Recyclable<T>::hash_i (void) const
+{
+ return this->t_.hash ();
+}
+
+template <class T> ASYS_INLINE T &
+ACE_Refcounted_Hash_Recyclable<T>::subject (void)
+{
+ return this->t_;
+}
+
+template <class T> ASYS_INLINE int
+ACE_Refcounted_Hash_Recyclable<T>::operator== (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const
+{
+ return this->recycle_state () == rhs.recycle_state () &&
+ this->t_ == rhs.t_;
+}
+
+template <class T> ASYS_INLINE int
+ACE_Refcounted_Hash_Recyclable<T>::operator!= (const ACE_Refcounted_Hash_Recyclable<T> &rhs) const
+{
+ return !this->operator== (rhs);
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_NOOP_Creation_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&)
+{
+ ACE_TRACE ("ACE_NOOP_Creation_Strategy<SVC_HANDLER>::make_svc_handler");
+ return 0;
+}
+
+template <class SVC_HANDLER> ASYS_INLINE int
+ACE_NOOP_Concurrency_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *,
+ void *)
+{
+ ACE_TRACE ("ACE_NOOP_Concurrency_Strategy<SVC_HANDLER>::activate_svc_handler");
+ return 0;
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ASYS_INLINE int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::make_svc_handler
+ (SVC_HANDLER *&sh)
+{
+ return this->creation_strategy_->make_svc_handler (sh);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ASYS_INLINE int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::activate_svc_handler
+ (SVC_HANDLER *svc_handler)
+{
+ return this->concurrency_strategy_->activate_svc_handler (svc_handler);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ASYS_INLINE int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::assign_recycler
+ (SVC_HANDLER *svc_handler,
+ ACE_Connection_Recycling_Strategy *recycler,
+ const void *recycling_act)
+{
+ return this->recycling_strategy_->assign_recycler (svc_handler,
+ recycler,
+ recycling_act);
+}
+
+template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> ASYS_INLINE int
+ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::prepare_for_recycling
+ (SVC_HANDLER *svc_handler)
+{
+ return this->recycling_strategy_->prepare_for_recycling (svc_handler);
+}
diff --git a/ace/Connection/WIN32_Asynch_IO.cpp b/ace/Connection/WIN32_Asynch_IO.cpp
new file mode 100644
index 00000000000..69d504e3792
--- /dev/null
+++ b/ace/Connection/WIN32_Asynch_IO.cpp
@@ -0,0 +1,2320 @@
+// $Id$
+
+#include "ace/WIN32_Asynch_IO.h"
+
+// ACE_RCSID(ace, Asynch_IO, "$Id$")
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+
+#include "ace/WIN32_Proactor.h"
+#include "ace/Message_Block.h"
+#include "ace/Service_Config.h"
+#include "ace/INET_Addr.h"
+#include "ace/Task_T.h"
+
+u_long
+ACE_WIN32_Asynch_Result::bytes_transferred (void) const
+{
+ return this->bytes_transferred_;
+}
+
+const void *
+ACE_WIN32_Asynch_Result::act (void) const
+{
+ return this->act_;
+}
+
+int
+ACE_WIN32_Asynch_Result::success (void) const
+{
+ return this->success_;
+}
+
+const void *
+ACE_WIN32_Asynch_Result::completion_key (void) const
+{
+ return this->completion_key_;
+}
+
+u_long
+ACE_WIN32_Asynch_Result::error (void) const
+{
+ return this->error_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Result::event (void) const
+{
+ return this->hEvent;
+}
+
+u_long
+ACE_WIN32_Asynch_Result::offset (void) const
+{
+ return this->Offset;
+}
+
+u_long
+ACE_WIN32_Asynch_Result::offset_high (void) const
+{
+ return this->OffsetHigh;
+}
+
+int
+ACE_WIN32_Asynch_Result::priority (void) const
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+int
+ACE_WIN32_Asynch_Result::signal_number (void) const
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+int
+ACE_WIN32_Asynch_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ // Get to the platform specific implementation.
+ ACE_WIN32_Proactor *win32_proactor = ACE_dynamic_cast (ACE_WIN32_Proactor *,
+ proactor);
+
+ if (win32_proactor == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Dynamic cast to WIN32 Proactor failed\n")),
+ -1);
+
+ // Post myself.
+ return win32_proactor->post_completion (this);
+}
+
+void
+ACE_WIN32_Asynch_Result::set_bytes_transferred (u_long nbytes)
+{
+ this->bytes_transferred_ = nbytes;
+}
+
+void
+ACE_WIN32_Asynch_Result::set_error (u_long errcode)
+{
+ this->error_ = errcode;
+}
+
+ACE_WIN32_Asynch_Result::~ACE_WIN32_Asynch_Result (void)
+{
+}
+
+ACE_WIN32_Asynch_Result::ACE_WIN32_Asynch_Result (ACE_Handler &handler,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ OVERLAPPED (),
+ handler_ (handler),
+ act_ (act),
+ bytes_transferred_ (0),
+ success_ (0),
+ completion_key_ (0),
+ error_ (0)
+{
+ // Set the ACE_OVERLAPPED structure
+ this->Internal = 0;
+ this->InternalHigh = 0;
+ this->Offset = offset;
+ this->OffsetHigh = offset_high;
+ this->hEvent = event;
+
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+}
+
+int
+ACE_WIN32_Asynch_Operation::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ this->proactor_ = proactor;
+ this->handler_ = &handler;
+ this->handle_ = handle;
+
+ // Grab the handle from the <handler> if <handle> is invalid
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ this->handle_ = this->handler_->handle ();
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ // Register with the <proactor>.
+ return this->win32_proactor_->register_handle (this->handle_,
+ completion_key);
+}
+
+int
+ACE_WIN32_Asynch_Operation::cancel (void)
+{
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) \
+ && ( (defined (_MSC_VER) && (_MSC_VER > 1020)) \
+ || (defined (__BORLANDC__) && (__BORLANDC__ >= 0x530)))
+ // All I/O operations that are canceled will complete with the error
+ // ERROR_OPERATION_ABORTED. All completion notifications for the I/O
+ // operations will occur normally.
+
+ // @@ This API returns 0 on failure. So, I am returning -1 in that
+ // case. Is that right? (Alex).
+
+ int result = (int) ::CancelIo (this->handle_);
+
+ if (result == 0)
+ // Couldnt cancel the operations.
+ return 2;
+
+ // result is non-zero. All the operations are cancelled then.
+ return 0;
+
+#else /* Not ACE_HAS_WINNT4 && ACE_HAS_WINNT4!=0 && _MSC... */
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_AIO_CALLS */
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Operation::proactor (void) const
+{
+ return this->proactor_;
+}
+
+ACE_WIN32_Asynch_Operation::ACE_WIN32_Asynch_Operation (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ win32_proactor_ (win32_proactor),
+ proactor_ (0),
+ handler_ (0),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+ACE_WIN32_Asynch_Operation::~ACE_WIN32_Asynch_Operation (void)
+{
+}
+
+// ************************************************************
+
+u_long
+ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read (void) const
+{
+ return this->bytes_to_read_;
+}
+
+ACE_Message_Block &
+ACE_WIN32_Asynch_Read_Stream_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_Stream_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+ACE_WIN32_Asynch_Read_Stream_Result::ACE_WIN32_Asynch_Read_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_read_ (bytes_to_read),
+ message_block_ (message_block),
+ handle_ (handle)
+{
+}
+
+void
+ACE_WIN32_Asynch_Read_Stream_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_Stream::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_stream (result);
+}
+
+ACE_WIN32_Asynch_Read_Stream_Result::~ACE_WIN32_Asynch_Read_Stream_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Read_Stream_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_Stream_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_Stream_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Stream_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_Stream_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Stream_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Stream_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Read_Stream::ACE_WIN32_Asynch_Read_Stream (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Stream_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_Stream_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared read
+ ssize_t return_val = this->shared_read (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_WIN32_Asynch_Read_Stream::~ACE_WIN32_Asynch_Read_Stream (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream::shared_read (ACE_WIN32_Asynch_Read_Stream_Result *result)
+{
+ u_long bytes_read;
+
+ result->set_error (0); // Clear error before starting IO.
+
+ // Initiate the read
+ int initiate_result = ::ReadFile (result->handle (),
+ result->message_block ().wr_ptr (),
+ result->bytes_to_read (),
+ &bytes_read,
+ result);
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ return 0;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ReadFile")));
+ }
+
+ return -1;
+ }
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Read_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Read_Stream::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Read_Stream::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write (void) const
+{
+ return this->bytes_to_write_;
+}
+
+ACE_Message_Block &
+ACE_WIN32_Asynch_Write_Stream_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_Stream_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+ACE_WIN32_Asynch_Write_Stream_Result::ACE_WIN32_Asynch_Write_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_write_ (bytes_to_write),
+ message_block_ (message_block),
+ handle_ (handle)
+{
+}
+
+void
+ACE_WIN32_Asynch_Write_Stream_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by <GetQueuedCompletionStatus>.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.rd_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Stream::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_stream (result);
+}
+
+ACE_WIN32_Asynch_Write_Stream_Result::~ACE_WIN32_Asynch_Write_Stream_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Write_Stream_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_Stream_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_Stream_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Stream_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_Stream_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Stream_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Stream_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Write_Stream::ACE_WIN32_Asynch_Write_Stream (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Stream_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_Stream_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared write
+ ssize_t return_val = this->shared_write (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_WIN32_Asynch_Write_Stream::~ACE_WIN32_Asynch_Write_Stream (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream::shared_write (ACE_WIN32_Asynch_Write_Stream_Result *result)
+{
+ u_long bytes_written;
+
+ result->set_error (0); // Clear error before starting IO.
+
+ // Initiate the write
+ int initiate_result = ::WriteFile (result->handle (),
+ result->message_block ().rd_ptr (),
+ result->bytes_to_write (),
+ &bytes_written,
+ result);
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ return 0;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("WriteFile")));
+ }
+ return -1;
+ }
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Write_Stream::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Write_Stream::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Write_Stream::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_WIN32_Asynch_Read_File_Result::ACE_WIN32_Asynch_Read_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Stream_Result_Impl (),
+ ACE_Asynch_Read_File_Result_Impl (),
+ ACE_WIN32_Asynch_Read_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number)
+{
+ this->Offset = offset;
+ this->OffsetHigh = offset_high;
+}
+
+void
+ACE_WIN32_Asynch_Read_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus.
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_file (result);
+}
+
+ACE_WIN32_Asynch_Read_File_Result::~ACE_WIN32_Asynch_Read_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Read_File_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_File_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Read_File_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_File_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_File_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_File_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_File_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_File_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Read_File_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Read_File_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+// The following methods belong to
+// ACE_WIN32_Asynch_Read_Stream_Result. They are here to avoid VC++
+// warnings. These methods route their call to the
+// ACE_WIN32_Asynch_Read_Stream_Result base class.
+
+u_long
+ACE_WIN32_Asynch_Read_File_Result::bytes_to_read (void) const
+{
+ return ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read ();
+}
+
+ACE_Message_Block &
+ACE_WIN32_Asynch_Read_File_Result::message_block (void) const
+{
+ return ACE_WIN32_Asynch_Read_Stream_Result::message_block ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_File_Result::handle (void) const
+{
+ return ACE_WIN32_Asynch_Read_Stream_Result::handle ();
+}
+
+int
+ACE_WIN32_Asynch_Read_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+// ************************************************************
+
+ACE_WIN32_Asynch_Read_File::ACE_WIN32_Asynch_Read_File (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Stream_Impl (),
+ ACE_Asynch_Read_File_Impl (),
+ ACE_WIN32_Asynch_Read_Stream (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_WIN32_Asynch_Read_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_File_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared read
+ ssize_t return_val = this->shared_read (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_WIN32_Asynch_Read_File::~ACE_WIN32_Asynch_Read_File (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_WIN32_Asynch_Read_Stream::read (message_block,
+ bytes_to_read,
+ act,
+ priority,
+ signal_number);
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Read_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Read_File::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Read_File::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_WIN32_Asynch_Write_File_Result::ACE_WIN32_Asynch_Write_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Stream_Result_Impl (),
+ ACE_Asynch_Write_File_Result_Impl (),
+ ACE_WIN32_Asynch_Write_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number)
+{
+ this->Offset = offset;
+ this->OffsetHigh = offset_high;
+}
+
+void
+ACE_WIN32_Asynch_Write_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.rd_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Write_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_file (result);
+}
+
+ACE_WIN32_Asynch_Write_File_Result::~ACE_WIN32_Asynch_Write_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Write_File_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_File_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Write_File_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_File_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_File_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_File_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_File_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_File_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Write_File_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Write_File_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+// The following methods belong to
+// ACE_WIN32_Asynch_Write_Stream_Result. They are here to avoid VC++
+// warnings. These methods route their call to the
+// ACE_WIN32_Asynch_Write_Stream_Result base class.
+
+u_long
+ACE_WIN32_Asynch_Write_File_Result::bytes_to_write (void) const
+{
+ return ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write ();
+}
+
+ACE_Message_Block &
+ACE_WIN32_Asynch_Write_File_Result::message_block (void) const
+{
+ return ACE_WIN32_Asynch_Write_Stream_Result::message_block ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_File_Result::handle (void) const
+{
+ return ACE_WIN32_Asynch_Write_Stream_Result::handle ();
+}
+
+int
+ACE_WIN32_Asynch_Write_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Write_File::ACE_WIN32_Asynch_Write_File (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Stream_Impl (),
+ ACE_Asynch_Write_File_Impl (),
+ ACE_WIN32_Asynch_Write_Stream (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ ACE_WIN32_Asynch_Write_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_File_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // Shared write
+ ssize_t return_val = this->shared_write (result);
+
+ // Upon errors
+ if (return_val == -1)
+ delete result;
+
+ return return_val;
+}
+
+ACE_WIN32_Asynch_Write_File::~ACE_WIN32_Asynch_Write_File (void)
+{
+}
+
+int
+ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ return ACE_WIN32_Asynch_Write_Stream::write (message_block,
+ bytes_to_write,
+ act,
+ priority,
+ signal_number);
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Write_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Write_File::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Write_File::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+u_long
+ACE_WIN32_Asynch_Accept_Result::bytes_to_read (void) const
+{
+ return this->bytes_to_read_;
+}
+
+ACE_Message_Block &
+ACE_WIN32_Asynch_Accept_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Accept_Result::listen_handle (void) const
+{
+ return this->listen_handle_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Accept_Result::accept_handle (void) const
+{
+ return this->accept_handle_;
+}
+
+ACE_WIN32_Asynch_Accept_Result::ACE_WIN32_Asynch_Accept_Result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Accept_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_read_ (bytes_to_read),
+ message_block_ (message_block),
+ listen_handle_ (listen_handle),
+ accept_handle_ (accept_handle)
+{
+}
+
+void
+ACE_WIN32_Asynch_Accept_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ this->message_block_.wr_ptr (bytes_transferred);
+
+ // Create the interface result class.
+ ACE_Asynch_Accept::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_accept (result);
+}
+
+ACE_WIN32_Asynch_Accept_Result::~ACE_WIN32_Asynch_Accept_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Accept_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Accept_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Accept_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Accept_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Accept_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Accept_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Accept_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Accept_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Accept_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Accept_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Accept_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Accept::ACE_WIN32_Asynch_Accept (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Accept_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Accept::accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ // Sanity check: make sure that enough space has been allocated by
+ // the caller.
+ size_t address_size = sizeof (sockaddr_in) + sizeof (sockaddr);
+ size_t space_in_use = message_block.wr_ptr () - message_block.base ();
+ size_t total_size = message_block.size ();
+ size_t available_space = total_size - space_in_use;
+ size_t space_needed = bytes_to_read + 2 * address_size;
+ if (available_space < space_needed)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("Buffer too small\n")), -1);
+
+ // WIN Specific.
+
+ int close_accept_handle = 0;
+ // If the <accept_handle> is invalid, we will create a new socket.
+ if (accept_handle == ACE_INVALID_HANDLE)
+ {
+ accept_handle = ACE_OS::socket (PF_INET,
+ SOCK_STREAM,
+ 0);
+ if (accept_handle == ACE_INVALID_HANDLE)
+ {
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_OS::socket")));
+ }
+ return -1;
+ }
+ else
+ // Remember to close the socket down if failures occur.
+ close_accept_handle = 1;
+ }
+
+ // Common code for both WIN and POSIX.
+ ACE_WIN32_Asynch_Accept_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Accept_Result (*this->handler_,
+ this->handle_,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ u_long bytes_read;
+
+ // Initiate the accept.
+ int initiate_result = ::AcceptEx ((SOCKET) result->listen_handle (),
+ (SOCKET) result->accept_handle (),
+ result->message_block ().wr_ptr (),
+ result->bytes_to_read (),
+ address_size,
+ address_size,
+ &bytes_read,
+ result);
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ return 0;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (close_accept_handle == 1)
+ // Close the newly created socket
+ ACE_OS::closesocket (accept_handle);
+
+ // Cleanup dynamically allocated Asynch_Result.
+ delete result;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ReadFile")));
+ }
+ return -1;
+ }
+#else /* ACE_HAS_WINNT4 .......|| ACE_HAS_AIO_CALLS */
+ ACE_UNUSED_ARG (message_block);
+ ACE_UNUSED_ARG (bytes_to_read);
+ ACE_UNUSED_ARG (accept_handle);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) || (defined (ACE_HAS_AIO_CALLS) */
+}
+
+ACE_WIN32_Asynch_Accept::~ACE_WIN32_Asynch_Accept (void)
+{
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Accept::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Accept::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Accept::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Transmit_File_Result::socket (void) const
+{
+ return this->socket_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Transmit_File_Result::file (void) const
+{
+ return this->file_;
+}
+
+ACE_Asynch_Transmit_File::Header_And_Trailer *
+ACE_WIN32_Asynch_Transmit_File_Result::header_and_trailer (void) const
+{
+ return this->header_and_trailer_;
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::bytes_to_write (void) const
+{
+ return this->bytes_to_write_;
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::bytes_per_send (void) const
+{
+ return this->bytes_per_send_;
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_WIN32_Asynch_Transmit_File_Result::ACE_WIN32_Asynch_Transmit_File_Result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Transmit_File_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, offset, offset_high, priority, signal_number),
+ socket_ (socket),
+ file_ (file),
+ header_and_trailer_ (header_and_trailer),
+ bytes_to_write_ (bytes_to_write),
+ bytes_per_send_ (bytes_per_send),
+ flags_ (flags)
+{
+}
+
+void
+ACE_WIN32_Asynch_Transmit_File_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // We will not do this because (a) the header and trailer blocks may
+ // be the same message_blocks and (b) in cases of failures we have
+ // no idea how much of what (header, data, trailer) was sent.
+ /*
+ if (this->success_ && this->header_and_trailer_ != 0)
+ {
+ ACE_Message_Block *header = this->header_and_trailer_->header ();
+ if (header != 0)
+ header->rd_ptr (this->header_and_trailer_->header_bytes ());
+
+ ACE_Message_Block *trailer = this->header_and_trailer_->trailer ();
+ if (trailer != 0)
+ trailer->rd_ptr (this->header_and_trailer_->trailer_bytes ());
+ }
+ */
+
+ // Create the interface result class.
+ ACE_Asynch_Transmit_File::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_transmit_file (result);
+}
+
+ACE_WIN32_Asynch_Transmit_File_Result::~ACE_WIN32_Asynch_Transmit_File_Result (void)
+{
+}
+
+// Base class operations. These operations are here to kill dominance
+// warnings. These methods call the base class methods.
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Transmit_File_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Transmit_File_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Transmit_File_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Transmit_File_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Transmit_File::ACE_WIN32_Asynch_Transmit_File (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Transmit_File_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
+ ACE_WIN32_Asynch_Transmit_File_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Transmit_File_Result (*this->handler_,
+ this->handle_,
+ file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ ACE_LPTRANSMIT_FILE_BUFFERS transmit_buffers = 0;
+ if (result->header_and_trailer () != 0)
+ transmit_buffers = result->header_and_trailer ()->transmit_buffers ();
+
+ // Initiate the transmit file
+ int initiate_result = ::TransmitFile ((SOCKET) result->socket (),
+ result->file (),
+ result->bytes_to_write (),
+ result->bytes_per_send (),
+ result,
+ transmit_buffers,
+ result->flags ());
+ if (initiate_result == 1)
+ // Immediate success: the OVERLAPPED will still get queued.
+ return 1;
+
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ return 0;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ // Cleanup dynamically allocated Asynch_Result
+ delete result;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("TransmitFile")));
+ }
+ return -1;
+ }
+#else /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) */
+ ACE_UNUSED_ARG (file);
+ ACE_UNUSED_ARG (header_and_trailer);
+ ACE_UNUSED_ARG (bytes_to_write);
+ ACE_UNUSED_ARG (offset);
+ ACE_UNUSED_ARG (offset_high);
+ ACE_UNUSED_ARG (bytes_per_send);
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (act);
+ ACE_UNUSED_ARG (priority);
+ ACE_UNUSED_ARG (signal_number);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_AIO_CALLS */
+}
+
+ACE_WIN32_Asynch_Transmit_File::~ACE_WIN32_Asynch_Transmit_File (void)
+{
+}
+
+// Methods belong to ACE_WIN32_Asynch_Operation base class. These
+// methods are defined here to avoid VC++ warnings. They route the
+// call to the ACE_WIN32_Asynch_Operation base class.
+
+int
+ACE_WIN32_Asynch_Transmit_File::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Transmit_File::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Transmit_File::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Dgram_Result::bytes_to_read (void) const
+{
+ return this->bytes_to_read_;
+}
+
+ACE_Message_Block*
+ACE_WIN32_Asynch_Read_Dgram_Result::message_block (void) const
+{
+ return this->message_block_;
+}
+
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::remote_address (ACE_Addr& addr) const
+{
+ int retVal = -1; // failure
+
+ // make sure the addresses are of the same type
+ if (addr.get_type () == this->remote_address_->get_type ())
+ { // copy the remote_address_ into addr
+ addr.set_addr (this->remote_address_->get_addr (),
+ this->remote_address_->get_size ());
+ retVal = 0; // success
+ }
+
+ return retVal;
+}
+
+sockaddr *
+ACE_WIN32_Asynch_Read_Dgram_Result::saddr () const
+{
+ return (sockaddr *) this->remote_address_->get_addr ();
+}
+
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_Dgram_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Dgram_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_Dgram_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Read_Dgram_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Dgram_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Read_Dgram_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Dgram_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Read_Dgram_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Read_Dgram_Result::ACE_WIN32_Asynch_Read_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ u_long bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Read_Dgram_Result_Impl(),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_read_ (bytes_to_read),
+ message_block_ (message_block),
+ remote_address_ (0),
+ addr_len_ (0),
+ flags_ (flags),
+ handle_ (handle)
+{
+ ACE_ASSERT(protocol_family == PF_INET); // only supporting INET addresses
+
+ ACE_NEW(remote_address_, ACE_INET_Addr);
+ addr_len_ = remote_address_->get_size();
+}
+
+void
+ACE_WIN32_Asynch_Read_Dgram_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ for (ACE_Message_Block* mb = this->message_block_; (mb != 0) && (bytes_transferred > 0); mb = mb->cont ())
+ {
+ if (mb->size () >= bytes_transferred)
+ {
+ mb->wr_ptr (bytes_transferred);
+ bytes_transferred = 0;
+ }
+ else
+ {
+ mb->wr_ptr (mb->size ());
+ bytes_transferred -= mb->size ();
+ }
+ }
+
+ // Adjust the address length
+ this->remote_address_->set_size (this->addr_len_);
+
+ // Create the interface result class.
+ ACE_Asynch_Read_Dgram::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_read_dgram (result);
+}
+
+ACE_WIN32_Asynch_Read_Dgram_Result::~ACE_WIN32_Asynch_Read_Dgram_Result (void)
+{
+ delete this->remote_address_;
+}
+
+//***************************************************************************
+
+ACE_WIN32_Asynch_Read_Dgram::~ACE_WIN32_Asynch_Read_Dgram (void)
+{
+}
+
+ssize_t
+ACE_WIN32_Asynch_Read_Dgram::recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ number_of_bytes_recvd = 0;
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Read_Dgram_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Read_Dgram_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ message_block->total_size(),
+ flags,
+ protocol_family,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // do the scatter/gather recv
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+ for (const ACE_Message_Block* msg = message_block; msg != 0; msg = msg->cont ())
+ {
+ iov[iovcnt].iov_base = msg->wr_ptr ();
+ iov[iovcnt].iov_len = msg->size ();
+ ++iovcnt;
+ if (iovcnt >= ACE_IOV_MAX)
+ {
+ delete result;
+ return -1;
+ }
+ }
+
+ size_t bytes_recvd = 0;
+ int initiate_result = ACE_OS::recvfrom (result->handle (),
+ iov,
+ iovcnt,
+ bytes_recvd,
+ result->flags_,
+ result->saddr (),
+ &(result->addr_len_),
+ result,
+ 0);
+ if (initiate_result == SOCKET_ERROR)
+ {
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ initiate_result = 0;
+ break;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("WSARecvFrom")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ }
+ else
+ {
+ // Immediate success: the OVERLAPPED will still get queued.
+ // number_of_bytes_recvd contains the number of bytes recvd
+ // addr contains the peer address
+ // flags was updated
+ number_of_bytes_recvd = bytes_recvd;
+ initiate_result = 1;
+ }
+
+ return initiate_result;
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Read_Dgram::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Read_Dgram::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_WIN32_Asynch_Read_Dgram::ACE_WIN32_Asynch_Read_Dgram (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Read_Dgram_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+//***********************************************
+
+u_long
+ACE_WIN32_Asynch_Write_Dgram_Result::bytes_to_write (void) const
+{
+ return this->bytes_to_write_;
+}
+
+ACE_Message_Block*
+ACE_WIN32_Asynch_Write_Dgram_Result::message_block () const
+{
+ return this->message_block_;
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram_Result::flags (void) const
+{
+ return this->flags_;
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_Dgram_Result::handle (void) const
+{
+ return this->handle_;
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Dgram_Result::bytes_transferred (void) const
+{
+ return ACE_WIN32_Asynch_Result::bytes_transferred ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_Dgram_Result::act (void) const
+{
+ return ACE_WIN32_Asynch_Result::act ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram_Result::success (void) const
+{
+ return ACE_WIN32_Asynch_Result::success ();
+}
+
+const void *
+ACE_WIN32_Asynch_Write_Dgram_Result::completion_key (void) const
+{
+ return ACE_WIN32_Asynch_Result::completion_key ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Dgram_Result::error (void) const
+{
+ return ACE_WIN32_Asynch_Result::error ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Asynch_Write_Dgram_Result::event (void) const
+{
+ return ACE_WIN32_Asynch_Result::event ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Dgram_Result::offset (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset ();
+}
+
+u_long
+ACE_WIN32_Asynch_Write_Dgram_Result::offset_high (void) const
+{
+ return ACE_WIN32_Asynch_Result::offset_high ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram_Result::priority (void) const
+{
+ return ACE_WIN32_Asynch_Result::priority ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram_Result::signal_number (void) const
+{
+ return ACE_WIN32_Asynch_Result::signal_number ();
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
+{
+ return ACE_WIN32_Asynch_Result::post_completion (proactor);
+}
+
+ACE_WIN32_Asynch_Write_Dgram_Result::ACE_WIN32_Asynch_Write_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_Asynch_Write_Dgram_Result_Impl(),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ bytes_to_write_ (bytes_to_write),
+ message_block_ (message_block),
+ flags_ (flags),
+ handle_ (handle)
+{
+}
+
+void
+ACE_WIN32_Asynch_Write_Dgram_Result::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ // Copy the data which was returned by GetQueuedCompletionStatus
+ this->bytes_transferred_ = bytes_transferred;
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ // Appropriately move the pointers in the message block.
+ for (ACE_Message_Block* mb = this->message_block_; (mb != 0) && (bytes_transferred > 0); mb = mb->cont ())
+ {
+ if (mb->length () >= bytes_transferred)
+ {
+ mb->rd_ptr (bytes_transferred);
+ bytes_transferred = 0;
+ }
+ else
+ {
+ size_t len = mb->length ();
+ mb->rd_ptr (len);
+ bytes_transferred -= len;
+ }
+ }
+
+ // Create the interface result class.
+ ACE_Asynch_Write_Dgram::Result result (this);
+
+ // Call the application handler.
+ this->handler_.handle_write_dgram (result);
+}
+
+ACE_WIN32_Asynch_Write_Dgram_Result::~ACE_WIN32_Asynch_Write_Dgram_Result (void)
+{
+}
+
+
+//***********************************************
+
+ACE_WIN32_Asynch_Write_Dgram::~ACE_WIN32_Asynch_Write_Dgram (void)
+{
+}
+
+ssize_t
+ACE_WIN32_Asynch_Write_Dgram::send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ const void *act,
+ int priority,
+ int signal_number)
+{
+ number_of_bytes_sent = 0;
+
+ // Create the Asynch_Result.
+ ACE_WIN32_Asynch_Write_Dgram_Result *result = 0;
+ ACE_NEW_RETURN (result,
+ ACE_WIN32_Asynch_Write_Dgram_Result (*this->handler_,
+ this->handle_,
+ message_block,
+ message_block->total_length(),
+ flags,
+ act,
+ this->win32_proactor_->get_handle (),
+ priority,
+ signal_number),
+ -1);
+
+ // do the scatter/gather recv
+ iovec iov[ACE_IOV_MAX];
+ int iovcnt = 0;
+ for (const ACE_Message_Block* msg = message_block; msg != 0; msg = msg->cont ())
+ {
+ iov[iovcnt].iov_base = msg->rd_ptr ();
+ iov[iovcnt].iov_len = msg->length ();
+ ++iovcnt;
+ if (iovcnt >= ACE_IOV_MAX)
+ {
+ delete result;
+ return -1;
+ }
+ }
+
+ size_t bytes_sent = 0;
+ int initiate_result = ACE_OS::sendto (result->handle (),
+ iov,
+ iovcnt,
+ bytes_sent,
+ result->flags_,
+ (sockaddr *) addr.get_addr (),
+ addr.get_size(),
+ result,
+ 0);
+
+
+ if (initiate_result == SOCKET_ERROR)
+ {
+ // If initiate failed, check for a bad error.
+ ACE_OS::set_errno_to_last_error ();
+ switch (errno)
+ {
+ case ERROR_IO_PENDING:
+ // The IO will complete proactively: the OVERLAPPED will still
+ // get queued.
+ initiate_result = 0;
+ break;
+
+ default:
+ // Something else went wrong: the OVERLAPPED will not get
+ // queued.
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("WSASendTo")));
+ }
+
+ delete result;
+ initiate_result = -1;
+ break;
+ }
+
+ }
+ else
+ {
+ // Immediate success: the OVERLAPPED will still get queued.
+ // number_of_bytes_recvd contains the number of bytes recvd
+ // addr contains the peer address
+ // flags was updated
+ number_of_bytes_sent = bytes_sent;
+ initiate_result = 1;
+ }
+
+ return initiate_result;
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram::open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor)
+{
+ return ACE_WIN32_Asynch_Operation::open (handler,
+ handle,
+ completion_key,
+ proactor);
+}
+
+int
+ACE_WIN32_Asynch_Write_Dgram::cancel (void)
+{
+ return ACE_WIN32_Asynch_Operation::cancel ();
+}
+
+ACE_Proactor *
+ACE_WIN32_Asynch_Write_Dgram::proactor (void) const
+{
+ return ACE_WIN32_Asynch_Operation::proactor ();
+}
+
+ACE_WIN32_Asynch_Write_Dgram::ACE_WIN32_Asynch_Write_Dgram (ACE_WIN32_Proactor *win32_proactor)
+ : ACE_Asynch_Operation_Impl (),
+ ACE_Asynch_Write_Dgram_Impl (),
+ ACE_WIN32_Asynch_Operation (win32_proactor)
+{
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_WINCE */
diff --git a/ace/Connection/WIN32_Asynch_IO.h b/ace/Connection/WIN32_Asynch_IO.h
new file mode 100644
index 00000000000..8dba2c3cbfc
--- /dev/null
+++ b/ace/Connection/WIN32_Asynch_IO.h
@@ -0,0 +1,1628 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file WIN32_Asynch_IO.h
+ *
+ * $Id$
+ *
+ *
+ * These classes only works on Win32 platforms.
+ *
+ * The implementation of <ACE_Asynch_Transmit_File> and
+ * <ACE_Asynch_Accept> are only supported if ACE_HAS_WINSOCK2 is
+ * defined or you are on WinNT 4.0 or higher.
+ *
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ */
+//=============================================================================
+
+#ifndef ACE_WIN32_ASYNCH_IO_H
+#define ACE_WIN32_ASYNCH_IO_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Addr.h"
+
+// Forward declaration
+class ACE_WIN32_Proactor;
+
+/**
+ * @class ACE_WIN32_Asynch_Result
+ *
+ * @brief An abstract class which adds information to the OVERLAPPED
+ * structure to make it more useful.
+ *
+ * An abstract base class from which you can obtain some basic
+ * information like the number of bytes transferred, the ACT
+ * associated with the asynchronous operation, indication of
+ * success or failure, etc. Subclasses may want to store more
+ * information that is particular to the asynchronous operation
+ * it represents.
+ */
+class ACE_Export ACE_WIN32_Asynch_Result : public virtual ACE_Asynch_Result_Impl,
+ public OVERLAPPED
+{
+ /// Factory class has special permissions.
+ friend class ACE_WIN32_Asynch_Accept;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Result (void);
+
+ /// Simulate error value to use in the post_completion ()
+ void set_error (u_long errcode);
+
+ /// Simulate value to use in the post_completion ()
+ void set_bytes_transferred (u_long nbytes);
+
+protected:
+ /// Constructor.
+ ACE_WIN32_Asynch_Result (ACE_Handler &handler,
+ const void* act,
+ ACE_HANDLE event,
+ u_long offset,
+ u_long offset_high,
+ int priority,
+ int signal_number = 0);
+
+ /// Handler that will be called back.
+ ACE_Handler &handler_;
+
+ /// ACT for this operation.
+ const void *act_;
+
+ /// Bytes transferred by this operation.
+ u_long bytes_transferred_;
+
+ /// Success indicator.
+ int success_;
+
+ /// ACT associated with handle.
+ const void *completion_key_;
+
+ /// Error if operation failed.
+ u_long error_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Operation
+ *
+ * @brief This class abstracts out the common things needed for
+ * implementing Asynch_Operation for WIN32 platform.
+ *
+ */
+class ACE_Export ACE_WIN32_Asynch_Operation : public virtual ACE_Asynch_Operation_Impl
+{
+public:
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ // = Access methods.
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// Constructor.
+ ACE_WIN32_Asynch_Operation (ACE_WIN32_Proactor *win32_proactor);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Operation (void);
+
+ /// WIn32 Proactor.
+ ACE_WIN32_Proactor *win32_proactor_;
+
+ /// Proactor that this asynch IO is registered with.
+ ACE_Proactor *proactor_;
+
+ /// Handler that will receive the callback.
+ ACE_Handler *handler_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_Stream_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Read_Stream::Result class.
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_Stream_Result : public virtual ACE_Asynch_Read_Stream_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory class will have special permissions.
+ friend class ACE_WIN32_Asynch_Read_Stream;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ // Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Read_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_Stream factory.
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Read_Stream_Result (void);
+
+ /// Bytes requested when the asynchronous read was initiated.
+ u_long bytes_to_read_;
+
+ /// Message block for reading the data into.
+ ACE_Message_Block &message_block_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_Stream
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a stream.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can
+ * started using this class. An ACE_Asynch_Read_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_stream>
+ * callback.
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_Stream : public virtual ACE_Asynch_Read_Stream_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Read_Stream (ACE_WIN32_Proactor *win32_proactor);
+
+ /// This starts off an asynchronous read. Upto <bytes_to_read> will
+ /// be read and stored in the <message_block>.
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Read_Stream (void);
+
+ // Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// This is the method which does the real work and is there so that
+ /// the ACE_Asynch_Read_File class can use it too.
+ int shared_read (ACE_WIN32_Asynch_Read_Stream_Result *result);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_Stream_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Write_Stream::Result class.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_Stream_Result : public virtual ACE_Asynch_Write_Stream_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory class willl have special permissions.
+ friend class ACE_WIN32_Asynch_Write_Stream;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Write_Stream_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_Stream factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Write_Stream_Result (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write_;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block_;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_Stream
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a stream.
+ *
+ *
+ * Once <open> is called, multiple asynchronous <writes>s can
+ * started using this class. A ACE_Asynch_Write_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * write completes through the
+ * <ACE_Handler::handle_write_stream> callback.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_Stream : public virtual ACE_Asynch_Write_Stream_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Write_Stream (ACE_WIN32_Proactor *win32_proactor);
+
+ /// This starts off an asynchronous write. Upto <bytes_to_write>
+ /// will be written from the <message_block>.
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Write_Stream (void);
+
+ // = Methods belonging to <ACE_WIN32_Asynch_Operation> base class.
+
+ // These methods are defined here to avoid VC++ warnings. They route
+ // the call to the <ACE_WIN32_Asynch_Operation> base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// This is the method which does the real work and is there so that
+ /// the ACE_Asynch_Write_File class can use it too.
+ int shared_write (ACE_WIN32_Asynch_Write_Stream_Result *result);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_File_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Read_File::Result class.
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_File_Result : public virtual ACE_Asynch_Read_File_Result_Impl,
+ public ACE_WIN32_Asynch_Read_Stream_Result
+{
+ /// Factory class will have special permissions.
+ friend class ACE_WIN32_Asynch_Read_File;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ // = These methods belong to ACE_WIN32_Asynch_Result class base
+ // class. These operations are here to kill some warnings. These
+ // methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ // The following methods belong to
+ // ACE_WIN32_Asynch_Read_Stream_Result. They are here to avoid VC++
+ // dominance warnings. These methods route their call to the
+ // ACE_WIN32_Asynch_Read_Stream_Result base class.
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Read_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_File factory.
+
+ /// ACE_Proactor will call this method when the read completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Read_File_Result (void);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_File
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a file.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can
+ * started using this class. A ACE_Asynch_Read_File::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_file>
+ * callback.
+ *
+ * This class differs slightly from ACE_Asynch_Read_Stream as it
+ * allows the user to specify an offset for the read.
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_File : public virtual ACE_Asynch_Read_File_Impl,
+ public ACE_WIN32_Asynch_Read_Stream
+{
+
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Read_File (ACE_WIN32_Proactor *win32_proactor);
+
+ /**
+ * This starts off an asynchronous read. Upto <bytes_to_read> will
+ * be read and stored in the <message_block>. The read will start
+ * at <offset> from the beginning of the file.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Read_File (void);
+
+ // = Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ /**
+ * This method belongs to ACE_WIN32_Asynch_Read_Stream. It is here
+ * to avoid the compiler warnings. We forward this call to the
+ * ACE_WIN32_Asynch_Read_Stream class.
+ */
+ int read (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_File_Result
+ *
+ * @brief This class provides implementation for
+ * ACE_Asynch_Write_File_Result for WIN32 platforms.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous write.
+ *
+ * This class differs slightly from
+ * ACE_Asynch_Write_Stream::Result as it calls back
+ * <ACE_Handler::handle_write_file> on the <handler> instead
+ * of <ACE_Handler::handle_write_stream>. No additional state
+ * is required by this class as ACE_Asynch_Result can store
+ * the <offset>.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_File_Result : public virtual ACE_Asynch_Write_File_Result_Impl,
+ public ACE_WIN32_Asynch_Write_Stream_Result
+{
+ /// Factory class will have special permission.
+ friend class ACE_WIN32_Asynch_Write_File;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ // The following methods belong to
+ // ACE_WIN32_Asynch_Read_Stream_Result. They are here to avoid VC++
+ // warnings. These methods route their call to the
+ // ACE_WIN32_Asynch_Read_Stream_Result base class.
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block that contains the data to be written.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Write_File_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_File factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Write_File_Result (void);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_File
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a file.
+ *
+ * Once <open> is called, multiple asynchronous <write>s can be
+ * started using this class. A ACE_Asynch_Write_File::Result
+ * will be passed back to the <handler> when the asynchronous
+ * writes completes through the <ACE_Handler::handle_write_file>
+ * callback.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_File : public virtual ACE_Asynch_Write_File_Impl,
+ public ACE_WIN32_Asynch_Write_Stream
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Write_File (ACE_WIN32_Proactor *win32_proactor);
+
+ /**
+ * This starts off an asynchronous write. Upto <bytes_to_write>
+ * will be write and stored in the <message_block>. The write will
+ * start at <offset> from the beginning of the file.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destrcutor.
+ virtual ~ACE_WIN32_Asynch_Write_File (void);
+
+ // = Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+private:
+ /**
+ * This method belongs to ACE_WIN32_Asynch_Write_Stream. It is here
+ * to avoid compiler warnings. This method is forwarded to the
+ * ACE_WIN32_Asynch_Write_Stream class.
+ */
+ int write (ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Accept_Result
+ *
+ * @brief This class implements ACE_Asynch_Accept::Result for WIN32
+ * platform.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous accept.
+ */
+class ACE_Export ACE_WIN32_Asynch_Accept_Result : public virtual ACE_Asynch_Accept_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory will have special permission.
+ friend class ACE_WIN32_Asynch_Accept;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous accept.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data.
+ ACE_Message_Block &message_block (void) const;
+
+ /// I/O handle used for accepting new connections.
+ ACE_HANDLE listen_handle (void) const;
+
+ /// I/O handle for the new connection.
+ ACE_HANDLE accept_handle (void) const;
+
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Accept_Result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Accept factory.
+
+ /// ACE_Proactor will call this method when the accept completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Accept_Result (void);
+
+ /// Bytes requested when the asynchronous read was initiated.
+ u_long bytes_to_read_;
+
+ /// Message block for reading the data into.
+ ACE_Message_Block &message_block_;
+
+ /// I/O handle used for accepting new connections.
+ ACE_HANDLE listen_handle_;
+
+ /// I/O handle for the new connection.
+ ACE_HANDLE accept_handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Accept
+ *
+ * @brief This class is a factory for starting off asynchronous accepts
+ * on a listen handle.
+ *
+ * Once <open> is called, multiple asynchronous <accept>s can
+ * started using this class. A ACE_Asynch_Accept::Result will
+ * be passed back to the <handler> when the asynchronous accept
+ * completes through the <ACE_Handler::handle_accept>
+ * callback.
+ */
+class ACE_Export ACE_WIN32_Asynch_Accept : public virtual ACE_Asynch_Accept_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Accept (ACE_WIN32_Proactor *win32_proactor);
+
+ /**
+ * This starts off an asynchronous accept. The asynchronous accept
+ * call also allows any initial data to be returned to the
+ * <handler>. Upto <bytes_to_read> will be read and stored in the
+ * <message_block>. The <accept_handle> will be used for the
+ * <accept> call. If (<accept_handle> == INVALID_HANDLE), a new
+ * handle will be created.
+ *
+ * <message_block> must be specified. This is because the address of
+ * the new connection is placed at the end of this buffer.
+ */
+ int accept (ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ ACE_HANDLE accept_handle,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ ~ACE_WIN32_Asynch_Accept (void);
+
+ // Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Transmit_File_Result
+ *
+ *
+ * @brief This class implements ACE_Asynch_Transmit_File::Result for
+ * WIN32 platforms.
+ *
+ * This class has all the information necessary for the
+ * <handler> to uniquiely identify the completion of the
+ * asynchronous transmit file.
+ */
+class ACE_Export ACE_WIN32_Asynch_Transmit_File_Result : public virtual ACE_Asynch_Transmit_File_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory class will have special permission.
+ friend class ACE_WIN32_Asynch_Transmit_File;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// Socket used for transmitting the file.
+ ACE_HANDLE socket (void) const;
+
+ /// File from which the data is read.
+ ACE_HANDLE file (void) const;
+
+ /// Header and trailer data associated with this transmit file.
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer (void) const;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous transmit file.
+ u_long bytes_to_write (void) const;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ u_long bytes_per_send (void) const;
+
+ /// Flags which were passed into transmit file.
+ u_long flags (void) const;
+
+ // Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Transmit_File_Result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Transmit_File factory.
+
+ /// Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Transmit_File_Result (void);
+
+ /// Network I/O handle.
+ ACE_HANDLE socket_;
+
+ /// File I/O handle.
+ ACE_HANDLE file_;
+
+ /// Header and trailer data associated with this transmit file.
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer_;
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous transmit file.
+ u_long bytes_to_write_;
+
+ /// Number of bytes per send requested at the start of the transmit
+ /// file.
+ u_long bytes_per_send_;
+
+ /// Flags which were passed into transmit file.
+ u_long flags_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Transmit_File
+ *
+ * @brief This class is a factory for starting off asynchronous
+ * transmit files on a stream.
+ *
+ * Once <open> is called, multiple asynchronous <transmit_file>s
+ * can started using this class. A
+ * ACE_Asynch_Transmit_File::Result will be passed back to the
+ * <handler> when the asynchronous transmit file completes
+ * through the <ACE_Handler::handle_transmit_file> callback.
+ *
+ * The transmit_file function transmits file data over a
+ * connected network connection. The function uses the operating
+ * system's cache manager to retrieve the file data. This
+ * function provides high-performance file data transfer over
+ * network connections. This function would be of great use in
+ * a Web Server, Image Server, etc.
+ */
+class ACE_Export ACE_WIN32_Asynch_Transmit_File : public virtual ACE_Asynch_Transmit_File_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Transmit_File (ACE_WIN32_Proactor *win32_proactor);
+
+ /**
+ * This starts off an asynchronous transmit file. The <file> is a
+ * handle to an open file. <header_and_trailer> is a pointer to a
+ * data structure that contains pointers to data to send before and
+ * after the file data is sent. Set this parameter to 0 if you only
+ * want to transmit the file data. Upto <bytes_to_write> will be
+ * written to the <socket>. If you want to send the entire file,
+ * let <bytes_to_write> = 0. <bytes_per_send> is the size of each
+ * block of data sent per send operation. Please read the Win32
+ * documentation on what the flags should be.
+ */
+ int transmit_file (ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ int priority,
+ int signal_number = 0);
+
+ /// Destructor.
+ ~ACE_WIN32_Asynch_Transmit_File (void);
+
+ // Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_Dgram_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Read_Dgram::Result class.
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_Dgram_Result : public virtual ACE_Asynch_Read_Dgram_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory class will have special permissions.
+ friend class ACE_WIN32_Asynch_Read_Dgram;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous read.
+ u_long bytes_to_read (void) const;
+
+ /// Message block which contains the read data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The address of where the packet came from
+ int remote_address (ACE_Addr& addr) const;
+
+ sockaddr *saddr () const;
+
+ /// The flags used in the read
+ int flags (void) const;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle (void) const;
+
+ // Base class operations. These operations are here to kill
+ // dominance warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Read_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ u_long bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Read_Dgram factory.
+
+ /// Proactor will call this method when the read completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Read_Dgram_Result (void);
+
+ /// Bytes requested when the asynchronous read was initiated.
+ u_long bytes_to_read_;
+
+ /// Message block for reading the data into.
+ ACE_Message_Block *message_block_;
+
+ /// The address of where the packet came from
+ ACE_Addr *remote_address_;
+
+ int addr_len_;
+
+ /// The flags used in the read
+ int flags_;
+
+ /// I/O handle used for reading.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Read_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous reads
+ * on a UDP socket.
+ *
+ * Once <open> is called, multiple asynchronous <read>s can be
+ * started using this class. An ACE_Asynch_Read_Dgram::Result
+ * will be passed back to the <handler> when the asynchronous
+ * reads completes through the <ACE_Handler::handle_read_stream>
+ * callback.
+ *
+ */
+class ACE_Export ACE_WIN32_Asynch_Read_Dgram : public virtual ACE_Asynch_Read_Dgram_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Read_Dgram (ACE_WIN32_Proactor *win32_proactor);
+ virtual ~ACE_WIN32_Asynch_Read_Dgram (void);
+
+ /** This starts off an asynchronous read. Upto
+ * <message_block->total_size()> will be read and stored in the
+ * <message_block>. <message_block>'s <wr_ptr> will be updated to reflect
+ * the added bytes if the read operation is successfully completed.
+ * Return code of 1 means immediate success and <number_of_bytes_recvd>
+ * will contain number of bytes read. The <ACE_Handler::handle_read_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->size()> bytes will be read into each <message block> for
+ * a total of <message_block->total_size()> bytes. All <message_block>'s
+ * <wr_ptr>'s will be updated to reflect the added bytes for each
+ * <message_block>
+ */
+ virtual ssize_t recv (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_recvd,
+ int flags,
+ int protocol_family,
+ const void *act,
+ int priority,
+ int signal_number);
+
+ // Methods belong to ACE_WIN32_Asynch_Operation base class. These
+ // methods are defined here to avoid VC++ warnings. They route the
+ // call to the ACE_WIN32_Asynch_Operation base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_WIN32_Asynch_Read_Dgram (void);
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_Dgram_Result
+ *
+ * @brief This is class provides concrete implementation for
+ * ACE_Asynch_Write_Dgram::Result class.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_Dgram_Result : public virtual ACE_Asynch_Write_Dgram_Result_Impl,
+ public ACE_WIN32_Asynch_Result
+{
+ /// Factory class willl have special permissions.
+ friend class ACE_WIN32_Asynch_Write_Dgram;
+
+ /// Proactor class has special permission.
+ friend class ACE_WIN32_Proactor;
+
+public:
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write (void) const;
+
+ /// Message block which contains the sent data
+ ACE_Message_Block *message_block (void) const;
+
+ /// The flags using in the write
+ int flags (void) const;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle (void) const;
+
+ // = Base class operations. These operations are here to kill some
+ // warnings. These methods call the base class methods.
+
+ /// Number of bytes transferred by the operation.
+ u_long bytes_transferred (void) const;
+
+ /// ACT associated with the operation.
+ const void *act (void) const;
+
+ /// Did the operation succeed?
+ int success (void) const;
+
+ /**
+ * This returns the ACT associated with the handle when it was
+ * registered with the I/O completion port. This ACT is not the
+ * same as the ACT associated with the asynchronous operation.
+ */
+ const void *completion_key (void) const;
+
+ /// Error value if the operation fail.
+ u_long error (void) const;
+
+ /// Event associated with the OVERLAPPED structure.
+ ACE_HANDLE event (void) const;
+
+ /// This really make sense only when doing file I/O.
+ u_long offset (void) const;
+
+ /// Offset_high associated with the OVERLAPPED structure.
+ u_long offset_high (void) const;
+
+ /// The priority of the asynchronous operation. Currently, this is
+ /// not supported on Win32.
+ int priority (void) const;
+
+ /// No-op. Returns 0.
+ int signal_number (void) const;
+
+ /// Post <this> to the Proactor's completion port.
+ int post_completion (ACE_Proactor_Impl *proactor);
+
+protected:
+ ACE_WIN32_Asynch_Write_Dgram_Result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+ // Constructor is protected since creation is limited to
+ // ACE_Asynch_Write_Stream factory.
+
+ /// ACE_Proactor will call this method when the write completes.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /// Destructor.
+ virtual ~ACE_WIN32_Asynch_Write_Dgram_Result (void);
+
+ /// The number of bytes which were requested at the start of the
+ /// asynchronous write.
+ u_long bytes_to_write_;
+
+ /// Message block used for the send.
+ ACE_Message_Block *message_block_;
+
+ /// The flags using in the write
+ int flags_;
+
+ /// I/O handle used for writing.
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Write_Dgram
+ *
+ * @brief This class is a factory for starting off asynchronous writes
+ * on a UDP socket.
+ *
+ *
+ * Once <open> is called, multiple asynchronous <writes>s can
+ * started using this class. A ACE_Asynch_Write_Stream::Result
+ * will be passed back to the <handler> when the asynchronous
+ * write completes through the
+ * <ACE_Handler::handle_write_stream> callback.
+ */
+class ACE_Export ACE_WIN32_Asynch_Write_Dgram : public virtual ACE_Asynch_Write_Dgram_Impl,
+ public ACE_WIN32_Asynch_Operation
+{
+public:
+ /// Constructor.
+ ACE_WIN32_Asynch_Write_Dgram (ACE_WIN32_Proactor *win32_proactor);
+ virtual ~ACE_WIN32_Asynch_Write_Dgram (void);
+
+ /** This starts off an asynchronous send. Upto
+ * <message_block->total_length()> will be sent. <message_block>'s
+ * <rd_ptr> will be updated to reflect the sent bytes if the send operation
+ * is successfully completed.
+ * Return code of 1 means immediate success and <number_of_bytes_sent>
+ * is updated to number of bytes sent. The <ACE_Handler::handle_write_dgram>
+ * method will still be called. Return code of 0 means the IO will
+ * complete proactively. Return code of -1 means there was an error, use
+ * errno to get the error code.
+ *
+ * Scatter/gather is supported on WIN32 by using the <message_block->cont()>
+ * method. Up to ACE_IOV_MAX <message_block>'s are supported. Upto
+ * <message_block->length()> bytes will be sent from each <message block>
+ * for a total of <message_block->total_length()> bytes. All
+ * <message_block>'s <rd_ptr>'s will be updated to reflect the bytes sent
+ * from each <message_block>.
+ */
+ virtual ssize_t send (ACE_Message_Block *message_block,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ const void *act,
+ int priority,
+ int signal_number);
+
+ // = Methods belonging to <ACE_WIN32_Asynch_Operation> base class.
+
+ // These methods are defined here to avoid VC++ warnings. They route
+ // the call to the <ACE_WIN32_Asynch_Operation> base class.
+
+ /**
+ * Initializes the factory with information which will be used with
+ * each asynchronous call. If (<handle> == ACE_INVALID_HANDLE),
+ * <ACE_Handler::handle> will be called on the <handler> to get the
+ * correct handle.
+ */
+ int open (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ const void *completion_key,
+ ACE_Proactor *proactor);
+
+ /**
+ * This cancels all pending accepts operations that were issued by
+ * the calling thread. The function does not cancel asynchronous
+ * operations issued by other threads.
+ */
+ int cancel (void);
+
+ /// Return the underlying proactor.
+ ACE_Proactor* proactor (void) const;
+
+protected:
+ /// Do-nothing constructor.
+ ACE_WIN32_Asynch_Write_Dgram (void);
+};
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+#include "ace/post.h"
+#endif /* ACE_WIN32_ASYNCH_IO_H */
diff --git a/ace/Demux/Event_Handler.cpp b/ace/Demux/Event_Handler.cpp
new file mode 100644
index 00000000000..8c82b408197
--- /dev/null
+++ b/ace/Demux/Event_Handler.cpp
@@ -0,0 +1,254 @@
+// Event_Handler.cpp
+// $Id$
+
+#include "ace/Demux/Event_Handler.h"
+#include "ace/Utils/Message_Block.h"
+#include "ace/OS/OS_Errno.h"
+#include "ace/Demux/Reactor.h"
+#include "ace/Demux/Thread_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Demux/Event_Handler.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Event_Handler, "$Id$")
+
+// Implement conceptually abstract virtual functions in the base class
+// so derived classes don't have to implement unused ones.
+
+ACE_Event_Handler::ACE_Event_Handler (ACE_Reactor *r,
+ int p)
+ : priority_ (p),
+ reactor_ (r)
+{
+ // ACE_TRACE ("ACE_Event_Handler::ACE_Event_Handler");
+}
+
+ACE_Event_Handler::~ACE_Event_Handler (void)
+{
+ // ACE_TRACE ("ACE_Event_Handler::~ACE_Event_Handler");
+ if (this->reactor_ != 0)
+ {
+ ACE_Errno_Guard guard (errno); // purge may get ENOTSUP
+ this->reactor_->purge_pending_notifications (this);
+ }
+}
+
+// Gets the file descriptor associated with this I/O device.
+
+ACE_HANDLE
+ACE_Event_Handler::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler::get_handle");
+ return ACE_INVALID_HANDLE;
+}
+
+// Sets the file descriptor associated with this I/O device.
+
+void
+ACE_Event_Handler::set_handle (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::set_handle");
+}
+
+// Gets the priority of this handler.
+
+int
+ACE_Event_Handler::priority (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler::priority");
+ return this->priority_;
+}
+
+// Sets the priority
+
+void
+ACE_Event_Handler::priority (int priority)
+{
+ ACE_TRACE ("ACE_Event_Handler::priority");
+ this->priority_ = priority;
+}
+
+// Called when the object is about to be removed from the Dispatcher
+// tables.
+
+int
+ACE_Event_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_close");
+ return -1;
+}
+
+// Called when input becomes available on fd.
+
+int
+ACE_Event_Handler::handle_input (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_input");
+ return -1;
+}
+
+// Called when output is possible on fd.
+
+int
+ACE_Event_Handler::handle_output (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_output");
+ return -1;
+}
+
+// Called when urgent data is available on fd.
+
+int
+ACE_Event_Handler::handle_exception (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_exception");
+ return -1;
+}
+
+// Called when timer expires, TV stores the current time.
+
+int
+ACE_Event_Handler::handle_timeout (const ACE_Time_Value &, const void *)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_timeout");
+ return -1;
+}
+
+// Called when a monitored Process exits
+
+int
+ACE_Event_Handler::handle_exit (ACE_Process *)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_exit");
+ return -1;
+}
+
+// Called when a registered signal occurs.
+
+int
+ACE_Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_signal");
+ return -1;
+}
+
+int
+ACE_Event_Handler::resume_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler::resume_handler");
+
+ // Return a default value and allow the reactor to take care of
+ // resuming the handler
+ return 0;
+}
+
+
+int
+ACE_Event_Handler::handle_qos (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_qos");
+ return -1;
+}
+
+int
+ACE_Event_Handler::handle_group_qos (ACE_HANDLE)
+{
+ ACE_TRACE ("ACE_Event_Handler::handle_group_qos");
+ return -1;
+}
+
+void
+ACE_Event_Handler::reactor (ACE_Reactor *reactor)
+{
+ ACE_TRACE ("ACE_Event_Handler::reactor");
+ this->reactor_ = reactor;
+}
+
+ACE_Reactor *
+ACE_Event_Handler::reactor (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler::reactor");
+ return this->reactor_;
+}
+
+#if !defined (ACE_HAS_WINCE)
+
+// Used to read from non-socket ACE_HANDLEs in our own thread to work
+// around Win32 limitations that don't allow us to select() on
+// non-sockets (such as ACE_STDIN). This is commonly used in
+// situations where the Reactor is used to demultiplex read events on
+// ACE_STDIN on UNIX. Note that <event_handler> must be a subclass of
+// <ACE_Event_Handler>. If the <get_handle> method of this event
+// handler returns <ACE_INVALID_HANDLE> we default to reading from
+// ACE_STDIN.
+
+void *
+ACE_Event_Handler::read_adapter (void *args)
+{
+ ACE_Event_Handler *this_ptr = (ACE_Event_Handler *) args;
+ ACE_HANDLE handle = ACE_STDIN;
+
+ while (this_ptr->handle_input (handle) != -1)
+ continue;
+
+ this_ptr->handle_close (handle,
+ ACE_Event_Handler::READ_MASK);
+ this_ptr->reactor ()->notify ();
+
+ return 0;
+}
+
+int
+ACE_Event_Handler::register_stdin_handler (ACE_Event_Handler *eh,
+ ACE_Reactor *reactor,
+ ACE_Thread_Manager *thr_mgr,
+ int flags)
+{
+#if defined (ACE_WIN32) || defined (ACE_PSOS)
+ ACE_UNUSED_ARG (reactor);
+
+ eh->reactor (reactor);
+ return thr_mgr->spawn (&read_adapter, (void *) eh, flags);
+#else
+ // Keep compilers happy.
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (thr_mgr);
+ return reactor->register_handler (ACE_STDIN,
+ eh,
+ ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 || ACE_PSOS */
+}
+
+int
+ACE_Event_Handler::remove_stdin_handler (ACE_Reactor *reactor,
+ ACE_Thread_Manager *thr_mgr)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (reactor);
+ ACE_UNUSED_ARG (thr_mgr);
+
+ // What should we do here?
+ ACE_NOTSUP_RETURN (-1);
+#else
+ // Keep compilers happy.
+ ACE_UNUSED_ARG (thr_mgr);
+ return reactor->remove_handler (ACE_STDIN,
+ ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 */
+}
+
+#endif /* ACE_HAS_WINCE */
+
+ACE_Notification_Buffer::ACE_Notification_Buffer (void)
+{
+ ACE_TRACE ("ACE_Notification_Buffer::ACE_Notification_Buffer");
+}
+
+ACE_Notification_Buffer::ACE_Notification_Buffer (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+ : eh_ (eh),
+ mask_ (mask)
+{
+ ACE_TRACE ("ACE_Notification_Buffer::ACE_Notification_Buffer");
+}
diff --git a/ace/Demux/Event_Handler.h b/ace/Demux/Event_Handler.h
new file mode 100644
index 00000000000..e2e5419594e
--- /dev/null
+++ b/ace/Demux/Event_Handler.h
@@ -0,0 +1,216 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Event_Handler.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_EVENT_HANDLER_H
+#define ACE_EVENT_HANDLER_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward declaration.
+class ACE_Message_Block;
+class ACE_Reactor;
+class ACE_Thread_Manager;
+class ACE_Process;
+
+typedef u_long ACE_Reactor_Mask;
+
+/**
+ * @class ACE_Event_Handler
+ *
+ * @brief Provides an abstract interface for handling various types of
+ * I/O, timer, and signal events.
+ *
+ * Subclasses read/write input/output on an I/O descriptor,
+ * handle an exception raised on an I/O descriptor, handle a
+ * timer's expiration, or handle a signal.
+ */
+class ACE_Export ACE_Event_Handler
+{
+public:
+ enum
+ {
+ LO_PRIORITY = 0,
+ HI_PRIORITY = 10,
+ NULL_MASK = 0,
+#if defined (ACE_USE_POLL)
+ READ_MASK = POLLIN,
+ WRITE_MASK = POLLOUT,
+ EXCEPT_MASK = POLLPRI,
+#else /* USE SELECT */
+ READ_MASK = (1 << 0),
+ WRITE_MASK = (1 << 1),
+ EXCEPT_MASK = (1 << 2),
+#endif /* ACE_USE_POLL */
+ ACCEPT_MASK = (1 << 3),
+ CONNECT_MASK = (1 << 4),
+ TIMER_MASK = (1 << 5),
+ QOS_MASK = (1 << 6),
+ GROUP_QOS_MASK = (1 << 7),
+ SIGNAL_MASK = (1 << 8),
+ ALL_EVENTS_MASK = READ_MASK |
+ WRITE_MASK |
+ EXCEPT_MASK |
+ ACCEPT_MASK |
+ CONNECT_MASK |
+ TIMER_MASK |
+ QOS_MASK |
+ GROUP_QOS_MASK |
+ SIGNAL_MASK,
+ RWE_MASK = READ_MASK |
+ WRITE_MASK |
+ EXCEPT_MASK,
+ DONT_CALL = (1 << 9)
+ };
+
+ /// Destructor is virtual to enable proper cleanup.
+ virtual ~ACE_Event_Handler (void);
+
+ /// Get the I/O handle.
+ /// Set the I/O handle.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual void set_handle (ACE_HANDLE);
+
+ // = Get/set priority
+
+ // Priorities run from MIN_PRIORITY (which is the "lowest priority")
+ // to MAX_PRIORITY (which is the "highest priority").
+ /// Get the priority of the Event_Handler.
+ /// Set the priority of the Event_Handler.
+ virtual int priority (void) const;
+ virtual void priority (int priority);
+
+ /// Called when input events occur (e.g., connection or data).
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ /// Called when output events are possible (e.g., when flow control
+ /// abates or non-blocking connection completes).
+ virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ /// Called when an exceptional events occur (e.g., SIGURG).
+ virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ /**
+ * Called when timer expires. <current_time> represents the current
+ * time that the <Event_Handler> was selected for timeout
+ * dispatching and <act> is the asynchronous completion token that
+ * was passed in when <schedule_timer> was invoked.
+ */
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *act = 0);
+
+ /// Called when a process exits.
+ virtual int handle_exit (ACE_Process *);
+
+ /// Called when a <handle_*()> method returns -1 or when the
+ /// <remove_handler> method is called on an <ACE_Reactor>. The
+ /// <close_mask> indicates which event has triggered the
+ /// <handle_close> method callback on a particular <handle>.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ /// Called when object is signaled by OS (either via UNIX signals or
+ /// when a Win32 object becomes signaled).
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+
+ /// Called to figure out whether the handler needs to resumed by the
+ /// reactor or the application can take care of it. The default
+ /// value of 0 would be returned which would allow the reactor to
+ /// take care of resumption of the handler. The application can
+ /// return a value more than zero and decide to resume the handler
+ /// themseleves.
+ virtual int resume_handler (void);
+
+ virtual int handle_qos (ACE_HANDLE = ACE_INVALID_HANDLE);
+ virtual int handle_group_qos (ACE_HANDLE = ACE_INVALID_HANDLE);
+
+ // = Accessors to set/get the various event demultiplexors.
+ virtual void reactor (ACE_Reactor *reactor);
+ virtual ACE_Reactor *reactor (void) const;
+
+#if !defined (ACE_HAS_WINCE)
+ /**
+ * Used to read from non-socket ACE_HANDLEs in our own thread to
+ * work around Win32 limitations that don't allow us to <select> on
+ * non-sockets (such as ACE_STDIN). This is commonly used in
+ * situations where the Reactor is used to demultiplex read events
+ * on ACE_STDIN on UNIX. Note that <event_handler> must be a
+ * subclass of <ACE_Event_Handler>. If the <get_handle> method of
+ * this event handler returns <ACE_INVALID_HANDLE> we default to
+ * reading from ACE_STDIN.
+ */
+ static void *read_adapter (void *event_handler);
+
+ /**
+ * Abstracts away from the differences between Win32 and ACE with
+ * respect to reading from ACE_STDIN, which is non-<select>'able on
+ * Win32.
+ */
+ static int register_stdin_handler (ACE_Event_Handler *eh,
+ ACE_Reactor *reactor,
+ ACE_Thread_Manager *thr_mgr,
+ int flags = THR_DETACHED);
+
+ /// Performs the inverse of the <register_stdin_handler> method.
+ static int remove_stdin_handler (ACE_Reactor *reactor,
+ ACE_Thread_Manager *thr_mgr);
+#endif /* ACE_HAS_WINCE */
+
+protected:
+ /// Force ACE_Event_Handler to be an abstract base class.
+ ACE_Event_Handler (ACE_Reactor * = 0,
+ int priority = ACE_Event_Handler::LO_PRIORITY);
+
+private:
+
+ /// Priority of this Event_Handler.
+ int priority_;
+
+ // = Pointers to the various event demultiplexors.
+ ACE_Reactor *reactor_;
+};
+
+/**
+ * @class ACE_Notification_Buffer
+ *
+ * @brief Simple wrapper for passing <ACE_Event_Handler *>s and
+ * <ACE_Reactor_Mask>s between threads.
+ */
+class ACE_Export ACE_Notification_Buffer
+{
+public:
+ ACE_Notification_Buffer (void);
+
+ ACE_Notification_Buffer (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// Default dtor.
+ ~ACE_Notification_Buffer (void);
+
+ /// Pointer to the Event_Handler that will be dispatched
+ /// by the main event loop.
+ ACE_Event_Handler *eh_;
+
+ /// Mask that indicates which method to call.
+ ACE_Reactor_Mask mask_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Demux/Event_Handler.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_EVENT_HANDLER_H */
diff --git a/ace/Demux/Event_Handler.i b/ace/Demux/Event_Handler.i
new file mode 100644
index 00000000000..6ecccb4b1db
--- /dev/null
+++ b/ace/Demux/Event_Handler.i
@@ -0,0 +1,10 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Event_Handler.i
+
+ACE_INLINE
+ACE_Notification_Buffer::~ACE_Notification_Buffer (void)
+{
+}
+
diff --git a/ace/Demux/Event_Handler_T.cpp b/ace/Demux/Event_Handler_T.cpp
new file mode 100644
index 00000000000..f0efd27b43f
--- /dev/null
+++ b/ace/Demux/Event_Handler_T.cpp
@@ -0,0 +1,63 @@
+// Event_Handler_T.cpp
+// $Id$
+
+#ifndef EVENT_HANDLER_T_C
+#define EVENT_HANDLER_T_C
+
+#include "ace/Event_Handler_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Event_Handler_T, "$Id$")
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Event_Handler_T.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Event_Handler_T)
+
+template <class T> void
+ACE_Event_Handler_T<T>::dump (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::dump");
+}
+
+template<class T>
+ACE_Event_Handler_T<T>::~ACE_Event_Handler_T (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::~ACE_Event_Handler_T");
+ if (this->delete_handler_)
+ delete this->op_handler_;
+}
+
+template <class T>
+ACE_Event_Handler_T<T>::ACE_Event_Handler_T (T *op_handler, int delete_handler,
+ GET_HANDLE get_handle,
+ IO_HANDLER input_h,
+ CL_HANDLER close_h,
+ SIG_HANDLER sig_h,
+ TO_HANDLER timeout_h,
+ IO_HANDLER output_h,
+ SET_HANDLE set_handle,
+ IO_HANDLER except_h)
+ : op_handler_ (op_handler),
+ input_handler_ (input_h),
+ output_handler_ (output_h),
+ except_handler_ (except_h),
+ to_handler_ (timeout_h),
+ cl_handler_ (close_h),
+ sig_handler_ (sig_h),
+ delete_handler_ (delete_handler),
+ set_handle_ (set_handle),
+ get_handle_ (get_handle)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::ACE_Event_Handler_T");
+}
+
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+#endif /* EVENT_HANDLER_T_C */
diff --git a/ace/Demux/Event_Handler_T.h b/ace/Demux/Event_Handler_T.h
new file mode 100644
index 00000000000..c6400f93281
--- /dev/null
+++ b/ace/Demux/Event_Handler_T.h
@@ -0,0 +1,187 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Event_Handler_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_EVENT_HANDLER_T_H
+#define ACE_EVENT_HANDLER_T_H
+#include "ace/pre.h"
+
+#include "ace/Event_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+/**
+ * @class ACE_Event_Handler_T
+ *
+ * @brief Enable a class that doesn't inherit from the
+ * ACE_Event_Handler to be incorporated into the ACE_Reactor
+ * framework. Thanks to Greg Lavender (g.lavender@isode.com)
+ * for sharing this idea.
+ *
+ * It is sometimes the case that an application has a hierarchy
+ * of operation dispatcher classes that have their own
+ * inheritance hierarchy but also would like to integrate with
+ * the ACE_Reactor. Rather than adopt a "mixin" approach, it is
+ * often cleaner to define a template as a subclass of
+ * ACE_Event_Handler and paramterize it with an operation
+ * dispatcher type.
+ * When constructing an instantiation of the ACE_Event_Handler_T
+ * object, a set of pointers to member functions must be
+ * provided so that when one of the handle_* methods is called
+ * by the ACE_Reactor, the appropriate method is called on the
+ * underlying operations object. This is done since in some
+ * cases it is useful to map any event that happens to the same
+ * method on an object.
+ * The ACE_Event_Handler_T template is instantiated by an
+ * operations object and registered with the ACE_Reactor, and it
+ * then calls the appropriate op_handler. So, it's basically
+ * just another level of indirection in event dispatching. The
+ * coupling betweent the ultimate handler of the event and the
+ * ACE_Event_Handler class is relaxed a bit by have this
+ * intermediate <op_handler_> object of type <T> around. The
+ * client object can then dynamically change the bindings for
+ * the various handlers so that during the life of one of the
+ * operation objects, it can change how it wants events to be
+ * handled. It just instantiates a new instance of the template
+ * with different bindings and reregisters this new object with
+ * the ACE_Reactor.
+ */
+template <class T>
+class ACE_Event_Handler_T : public ACE_Event_Handler
+{
+public:
+ // = Typedefs to simplify pointer-to-member-function registration.
+
+ // Get/set the underlying handle.
+ typedef ACE_HANDLE (T::*GET_HANDLE) (void) const;
+ typedef void (T::*SET_HANDLE) (ACE_HANDLE);
+
+ /// Handle I/O events.
+ typedef int (T::*IO_HANDLER) (ACE_HANDLE);
+
+ /// Handle timeout events.
+ typedef int (T::*TO_HANDLER) (const ACE_Time_Value &, const void *);
+
+ /// Handle close events.
+ typedef int (T::*CL_HANDLER) (ACE_HANDLE, ACE_Reactor_Mask);
+
+ /// = Initialization and termination methods.
+ typedef int (T::*SIG_HANDLER) (ACE_HANDLE, siginfo_t*, ucontext_t*);
+
+ /// Initialize the op_handler.
+ ACE_Event_Handler_T (T *op_handler,
+ int delete_handler,
+ GET_HANDLE get_handle = 0,
+ IO_HANDLER input = 0,
+ CL_HANDLER close = 0,
+ SIG_HANDLER sig = 0,
+ TO_HANDLER timeout = 0,
+ IO_HANDLER output = 0,
+ SET_HANDLE set_handle = 0,
+ IO_HANDLER except = 0);
+
+ /// Close down and delete the <op_handler>
+ ~ACE_Event_Handler_T (void);
+
+ // = Override all the ACE_Event_Handler methods.
+
+ // These methods all delegate down to the <T> operations handler.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual void set_handle (ACE_HANDLE);
+ virtual int handle_input (ACE_HANDLE fd = -1);
+ virtual int handle_output (ACE_HANDLE fd = -1);
+ virtual int handle_exception (ACE_HANDLE fd = -1);
+ virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask close_mask);
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+
+ // = Get/set the operations handler.
+ T *op_handler (void);
+ void op_handler (T *);
+
+ // = Get/set the target pointer-to-method used for dispatching.
+
+ GET_HANDLE handle_get (void);
+ void handle_get (GET_HANDLE);
+
+ SET_HANDLE handle_set (void);
+ void handle_set (SET_HANDLE);
+
+ IO_HANDLER input_handler (void);
+ void input_handler (IO_HANDLER);
+
+ IO_HANDLER output_handler (void);
+ void output_handler (IO_HANDLER);
+
+ IO_HANDLER except_handler (void);
+ void except_handler (IO_HANDLER);
+
+ TO_HANDLER to_handler (void);
+ void to_handler (TO_HANDLER);
+
+ CL_HANDLER cl_handler (void);
+ void cl_handler (CL_HANDLER);
+
+ SIG_HANDLER sig_handler (void);
+ void sig_handler (SIG_HANDLER);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Pointer to the object that handles all the delegated operations.
+ T *op_handler_;
+
+ // = Handle input, output, and exception events.
+ IO_HANDLER input_handler_;
+ IO_HANDLER output_handler_;
+ IO_HANDLER except_handler_;
+
+ /// Handle timeout events.
+ TO_HANDLER to_handler_;
+
+ /// Handle close events.
+ CL_HANDLER cl_handler_;
+
+ /// Handle signal events.
+ SIG_HANDLER sig_handler_;
+
+ /// Keeps track of whether we need to delete the handler in the
+ /// destructor.
+ int delete_handler_;
+
+ // = Get/set underlying handle.
+ SET_HANDLE set_handle_;
+ GET_HANDLE get_handle_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Event_Handler_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Event_Handler_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Event_Handler_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+#include "ace/post.h"
+#endif /* ACE_EVENT_HANDLER_H */
diff --git a/ace/Demux/Event_Handler_T.i b/ace/Demux/Event_Handler_T.i
new file mode 100644
index 00000000000..b31415f7b73
--- /dev/null
+++ b/ace/Demux/Event_Handler_T.i
@@ -0,0 +1,185 @@
+/* -*- C++ -*- */
+// $Id$
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::op_handler (T *op)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::op_handler");
+ this->op_handler_ = op;
+}
+
+template<class T> ACE_INLINE T *
+ACE_Event_Handler_T<T>::op_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::op_handler");
+ return this->op_handler_;
+}
+
+template<class T> ACE_INLINE ACE_HANDLE
+ACE_Event_Handler_T<T>::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::get_handle");
+ return this->get_handle_ == 0 ? -1 : (this->op_handler_->*get_handle_) ();
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::set_handle (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::set_handle");
+ if (this->set_handle_ != 0)
+ (this->op_handler_->*set_handle_) (h);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_input (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_input");
+ return this->input_handler_ == 0 ? 0 : (this->op_handler_->*input_handler_) (fd);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_output (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_output");
+ return this->output_handler_ == 0 ? 0 : (this->op_handler_->*output_handler_) (fd);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_exception (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_exception");
+ return this->except_handler_ == 0 ? 0 : (this->op_handler_->*except_handler_) (fd);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_timeout (const ACE_Time_Value &tv, const void *arg)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_timeout");
+ return this->to_handler_ == 0 ? 0 : (this->op_handler_->*to_handler_) (tv, arg);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask close_mask)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_close");
+ return this->cl_handler_ == 0 ? 0 : (this->op_handler_->*cl_handler_) (fd, close_mask);
+}
+
+template<class T> ACE_INLINE int
+ACE_Event_Handler_T<T>::handle_signal (int signum, siginfo_t *s, ucontext_t *u)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_signal");
+ return this->sig_handler_ == 0 ? 0 : (this->op_handler_->*sig_handler_) (signum, s, u);
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::GET_HANDLE
+ACE_Event_Handler_T<T>::handle_get (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_get");
+ return this->get_handle_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::handle_get (ACE_TYPENAME ACE_Event_Handler_T<T>::GET_HANDLE h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_get");
+ this->get_handle_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::SET_HANDLE
+ACE_Event_Handler_T<T>::handle_set (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_set");
+ return this->set_handle_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::handle_set (ACE_TYPENAME ACE_Event_Handler_T<T>::SET_HANDLE h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::handle_set");
+ this->set_handle_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER
+ACE_Event_Handler_T<T>::input_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::input_handler");
+ return this->input_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::input_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::input_handler");
+ this->input_handler_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER
+ACE_Event_Handler_T<T>::output_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::output_handler");
+ return this->output_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::output_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::output_handler");
+ this->output_handler_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER
+ACE_Event_Handler_T<T>::except_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::except_handler");
+ return this->except_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::except_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::IO_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::except_handler");
+ this->except_handler_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::TO_HANDLER
+ACE_Event_Handler_T<T>::to_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::to_handler");
+ return this->to_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::to_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::TO_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::to_handler");
+ this->to_handler_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::CL_HANDLER
+ACE_Event_Handler_T<T>::cl_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::cl_handler");
+ return this->cl_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::cl_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::CL_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::cl_handler");
+ this->cl_handler_ = h;
+}
+
+template<class T> ACE_INLINE ACE_TYPENAME ACE_Event_Handler_T<T>::SIG_HANDLER
+ACE_Event_Handler_T<T>::sig_handler (void)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::sig_handler");
+ return this->sig_handler_;
+}
+
+template<class T> ACE_INLINE void
+ACE_Event_Handler_T<T>::sig_handler (ACE_TYPENAME ACE_Event_Handler_T<T>::SIG_HANDLER h)
+{
+ ACE_TRACE ("ACE_Event_Handler_T<T>::sig_handler");
+ this->sig_handler_ = h;
+}
diff --git a/ace/Demux/FlReactor.cpp b/ace/Demux/FlReactor.cpp
new file mode 100644
index 00000000000..c9a64145ce7
--- /dev/null
+++ b/ace/Demux/FlReactor.cpp
@@ -0,0 +1,331 @@
+// $Id$
+
+#include "ace/FlReactor.h"
+#include "ace/Synch_T.h"
+
+ACE_RCSID(ace, FlReactor, "$Id$")
+
+#if defined (ACE_HAS_FL)
+
+#include <FL/Fl.h>
+
+ACE_ALLOC_HOOK_DEFINE (ACE_FlReactor)
+
+// Must be called with lock held
+ACE_FlReactor::ACE_FlReactor (size_t size,
+ int restart,
+ ACE_Sig_Handler *h)
+ : ACE_Select_Reactor (size, restart, h)
+{
+ // When the ACE_Select_Reactor is constructed it creates the notify
+ // pipe and registers it with the register_handler_i() method. The
+ // FlReactor overloads this method BUT because the
+ // register_handler_i occurs when constructing the base class
+ // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
+ // is called not the FlReactor register_handler_i(). This means
+ // that the notify pipe is registered with the ACE_Select_Reactor
+ // event handling code not the FlReactor and so notfications don't
+ // work. To get around this we simply close and re-opened the
+ // notification handler in the constructor of the FlReactor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->close ();
+ this->notify_handler_->open (this, 0);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_FlReactor::~ACE_FlReactor (void)
+{
+}
+
+// This is just the <wait_for_multiple_events> from ace/Reactor.cpp
+// but we use the Fl functions to wait for an event, not <select>
+
+int
+ACE_FlReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_FlReactor::wait_for_multiple_events");
+ int nfound;
+
+ do
+ {
+ max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
+
+ size_t width = this->handler_rep_.max_handlep1 ();
+ handle_set.rd_mask_ = this->wait_set_.rd_mask_;
+ handle_set.wr_mask_ = this->wait_set_.wr_mask_;
+ handle_set.ex_mask_ = this->wait_set_.ex_mask_;
+
+ // Check to make sure our handle's are all usable.
+ ACE_Select_Reactor_Handle_Set temp_set = handle_set;
+
+ ACE_Time_Value zero = ACE_Time_Value::zero;
+ if (ACE_OS::select (width,
+ temp_set.rd_mask_,
+ temp_set.wr_mask_,
+ temp_set.ex_mask_,
+ &zero) == -1)
+ return -1; // Bad file arguments...
+
+ // Instead of waiting using <select>, just use the Fl mechanism
+ // to wait for one or more events...
+
+ // Wait for something to happen.
+ double t = 0;
+ if (max_wait_time != 0)
+ t = max_wait_time->sec () + max_wait_time->usec () / 1000000.0F;
+
+ while (t > 0) {
+ t = Fl::wait (t);
+ }
+
+ // Reset the width, in case it changed during the upcalls.
+ width = this->handler_rep_.max_handlep1 ();
+
+ // Now actually read the result needed by the <Select_Reactor>
+ // using <select>.
+ zero = ACE_Time_Value::zero;
+ nfound = ACE_OS::select (width,
+ handle_set.rd_mask_,
+ handle_set.wr_mask_,
+ handle_set.ex_mask_,
+ &zero);
+
+ } while (nfound == -1 && this->handle_error () > 0);
+
+ if (nfound > 0)
+ {
+#if !defined (ACE_WIN32)
+ handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_WIN32 */
+ }
+ return nfound; // Timed out or input available
+}
+
+void
+ACE_FlReactor::fl_io_proc (int fd, void* reactor)
+{
+ ACE_FlReactor *self = ACE_static_cast(ACE_FlReactor *, reactor);
+ ACE_HANDLE handle = (ACE_HANDLE)fd; //ACE_reinterpret_cast(ACE_HANDLE, fd);
+
+ // my copy isn't const.
+ ACE_Time_Value zero = ACE_Time_Value::zero;
+
+ ACE_Select_Reactor_Handle_Set wait_set;
+
+ // Deal with one file event.
+
+ // - read which kind of event
+ if (self->wait_set_.rd_mask_.is_set (handle))
+ wait_set.rd_mask_.set_bit (handle);
+ if (self->wait_set_.wr_mask_.is_set (handle))
+ wait_set.wr_mask_.set_bit (handle);
+ if (self->wait_set_.ex_mask_.is_set (handle))
+ wait_set.ex_mask_.set_bit (handle);
+
+ int result = ACE_OS::select (fd + 1,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_, &zero);
+
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ // - Use only that one file event (removes events for other files).
+ if (result > 0)
+ {
+ if (wait_set.rd_mask_.is_set (handle))
+ dispatch_set.rd_mask_.set_bit (handle);
+ if (wait_set.wr_mask_.is_set (handle))
+ dispatch_set.wr_mask_.set_bit (handle);
+ if (wait_set.ex_mask_.is_set (handle))
+ dispatch_set.ex_mask_.set_bit (handle);
+
+ self->dispatch (1, dispatch_set);
+ }
+}
+
+void
+ACE_FlReactor::fl_timeout_proc (void* reactor)
+{
+ ACE_FlReactor *self = ACE_static_cast (ACE_FlReactor *, reactor);
+
+ // Deal with any timer events
+ ACE_Select_Reactor_Handle_Set handle_set;
+ self->dispatch (0, handle_set);
+ self->reset_timeout ();
+}
+
+
+int
+ACE_FlReactor::register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_FlReactor::register_handler_i");
+
+ int result = ACE_Select_Reactor::register_handler_i (handle,
+ handler, mask);
+ if (result == -1)
+ return -1;
+
+ int condition = 0;
+
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, FL_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, FL_WRITE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (condition, FL_EXCEPT);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, FL_READ);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK))
+ {
+ ACE_SET_BITS (condition, FL_WRITE); // connected, you may write
+ ACE_SET_BITS (condition, FL_READ); // connected, you have data/err
+ }
+
+ if (condition != 0)
+ {
+ Fl::add_fd ((int)handle, // ACE_reinterpret_cast(int,handle),
+ ACE_FlReactor::fl_io_proc,
+ this);
+ }
+ return 0;
+}
+
+int
+ACE_FlReactor::register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::register_handler_i (handles,
+ handler,
+ mask);
+}
+
+int
+ACE_FlReactor::remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_FlReactor::remove_handler_i");
+
+ // In the registration phase we registered first with
+ // ACE_Select_Reactor and then with X. Now we are now doing things
+ // in reverse order.
+
+ // First clean up the corresponding X11Input.
+ Fl::remove_fd ((int)handle); // ACE_reinterpret_cast(int,handle));
+
+ // Now let the reactor do its work.
+ return ACE_Select_Reactor::remove_handler_i (handle,
+ mask);
+}
+
+int
+ACE_FlReactor::remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::remove_handler_i (handles,
+ mask);
+}
+
+// The following function ensures there's an Fl timeout for the first
+// timeout in the Reactor's Timer_Queue.
+
+void
+ACE_FlReactor::reset_timeout (void)
+{
+ ACE_Time_Value *max_wait_time =
+ this->timer_queue_->calculate_timeout (0);
+
+ if (max_wait_time != 0)
+ {
+ float t = max_wait_time->sec ()
+ + max_wait_time->usec () / 1000000.0F;
+ Fl::add_timeout (t,
+ ACE_FlReactor::fl_timeout_proc,
+ this);
+ }
+}
+
+int
+ACE_FlReactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_FlReactor::reset_timer_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ int result =
+ ACE_Select_Reactor::reset_timer_interval (timer_id,
+ interval);
+
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+long
+ACE_FlReactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_FlReactor::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ long result = ACE_Select_Reactor::schedule_timer (handler,
+ arg,
+ delay_time,
+ interval);
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+int
+ACE_FlReactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_FlReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (handler,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+int
+ACE_FlReactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_FlReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (timer_id,
+ arg,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+#endif /* ACE_HAS_FL */
diff --git a/ace/Demux/FlReactor.h b/ace/Demux/FlReactor.h
new file mode 100644
index 00000000000..c9cb7670b0d
--- /dev/null
+++ b/ace/Demux/FlReactor.h
@@ -0,0 +1,111 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FlReactor.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@cs.wustl.edu>
+ * @author Based in part in the ACE_XtReactor implementation by
+ * @author Eric C. Newton's <ecn@clark.net>
+ * @author Kirill Rybaltchenko <Kirill.Rybaltchenko@cern.ch>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_FLREACTOR_H
+#define ACE_FLREACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_FL)
+
+/**
+ * @class ACE_FlReactor
+ *
+ * @brief A Reactor implementation that uses the Fast-Light (FL) toolkit
+ * for event demultiplexing. This will let us integrate the FL
+ * toolkit with ACE and/or TAO.
+ *
+ * As many other GUI toolkits FL supports a minimal set of
+ * callbacks to handle event demultiplexing, namely simple methods
+ * to add file descriptors to the event demuxing set or timeout
+ * events. This class adapts this simple mechanisms so they are
+ * compatible with ACE's Reactor.
+ */
+class ACE_Export ACE_FlReactor : public ACE_Select_Reactor
+{
+
+public:
+ // = Initialization and termination methods.
+ ACE_FlReactor (size_t size = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0);
+ virtual ~ACE_FlReactor (void);
+
+ // = Timer operations.
+ virtual long schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval);
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+ virtual int cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close = 1);
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+protected:
+ // = Register timers/handles with Fl.
+ /// Register a single <handler>.
+ virtual int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register a set of <handlers>.
+ virtual int register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Remove the <handler> associated with this <handle>.
+ virtual int remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// Remove a set of <handles>.
+ virtual int remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask);
+
+ /// Wait for events to occur.
+ virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+private:
+ /// This method ensures there's an Fl timeout for the first timeout
+ /// in the Reactor's Timer_Queue.
+ void reset_timeout (void);
+
+ // = Integrate with the FL callback function mechanism.
+ static void fl_io_proc (int fd, void*);
+ static void fl_timeout_proc (void*);
+
+ /// Deny access since member-wise won't work...
+ ACE_FlReactor (const ACE_FlReactor &);
+ ACE_FlReactor &operator = (const ACE_FlReactor &);
+};
+
+#if defined(__ACE_INLINE__)
+#include "ace/FlReactor.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_FL */
+
+#include "ace/post.h"
+#endif /* ACE_FLREACTOR_H */
diff --git a/ace/Demux/FlReactor.i b/ace/Demux/FlReactor.i
new file mode 100644
index 00000000000..74e88caa0c5
--- /dev/null
+++ b/ace/Demux/FlReactor.i
@@ -0,0 +1,2 @@
+// $Id$
+
diff --git a/ace/ATM/Makefile~ b/ace/Demux/Makefile
index faed337f700..f27d6158751 100644
--- a/ace/ATM/Makefile~
+++ b/ace/Demux/Makefile
@@ -1,35 +1,14 @@
# $Id$
#----------------------------------------------------------------------------
-# Makefile for the libACE_ATM
+# Makefile for the libACE_Demux
#----------------------------------------------------------------------------
MAKEFILE = Makefile
-LIBOS = libACE_ATM
+LIBOS = libACE_Demux
LIB = $(LIBOS).a
SHLIB = $(LIBOS).$(SOEXT)
-
-OS_FILES = \
- Base_Thread_Adapter\
- Basic_Types\
- Date_Time\
- gethrtime\
- Handle_Ops\
- Handle_Set\
- Init_ACE\
- OS\
- OS_Dirent\
- OS_Errno\
- OS_Log_Msg_Attributes\
- OS_Memory\
- OS_QoS\
- OS_String\
- OS_Thread_Adapter\
- OS_TLI\
- Sched_Params\
- Thread_Hook
-
#----------------------------------------------------------------------------
# Include macros and targets
#----------------------------------------------------------------------------
@@ -39,7 +18,23 @@ include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
####
#### ACE_COMPONENTS support.
####
-FILES += $(OS_FILES)
+FILES += \
+ Event_Handler\
+ Event_Handler_T\
+ FlReactor\
+ POSIX_Proactor\
+ Priority_Reactor\
+ Proactor\
+ QtReactor\
+ Reactor\
+ Reactor_Notification_Strategy\
+ Select_Reactor_Base\
+ Select_Reactor\
+ Select_Reactor_T\
+ SUN_Proactor\
+ TkReactor\
+ WFMO_Reactor\
+ WIN32_Proactor
LSRC = $(addsuffix .cpp,$(FILES))
@@ -66,24 +61,3 @@ clean:
# DO NOT DELETE THIS LINE -- g++dep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
-
-ATM_Acceptor.cpp
-ATM_Acceptor.h
-ATM_Acceptor.i
-ATM_Addr.cpp
-ATM_Addr.h
-ATM_Addr.i
-ATM_Connector.cpp
-ATM_Connector.h
-ATM_Connector.i
-ATM_Params.cpp
-ATM_Params.h
-ATM_Params.i
-ATM_QoS.cpp
-ATM_QoS.h
-ATM_QoS.i
-ATM_Stream.cpp
-ATM_Stream.h
-ATM_Stream.i
-Makefile
-Makefile~
diff --git a/ace/Demux/POSIX_Proactor.cpp b/ace/Demux/POSIX_Proactor.cpp
new file mode 100644
index 00000000000..8edad89edf9
--- /dev/null
+++ b/ace/Demux/POSIX_Proactor.cpp
@@ -0,0 +1,1935 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/POSIX_Proactor.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/POSIX_Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+# if defined (ACE_HAS_SYSINFO)
+# include <sys/systeminfo.h>
+# endif /* ACE_HAS_SYS_INFO */
+
+class ACE_Export ACE_POSIX_Wakeup_Completion : public ACE_POSIX_Asynch_Result
+{
+ // = TITLE
+ // This is result object is used by the <end_event_loop> of the
+ // ACE_Proactor interface to wake up all the threads blocking
+ // for completions.
+public:
+ ACE_POSIX_Wakeup_Completion (ACE_Handler &handler,
+ const void *act = 0,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+ // Constructor.
+
+ virtual ~ACE_POSIX_Wakeup_Completion (void);
+ // Destructor.
+
+
+ virtual void complete (u_long bytes_transferred = 0,
+ int success = 1,
+ const void *completion_key = 0,
+ u_long error = 0);
+ // This method calls the <handler>'s <handle_wakeup> method.
+};
+
+// *********************************************************************
+ACE_POSIX_Proactor::ACE_POSIX_Proactor (void)
+ : os_id_ (OS_UNDEFINED)
+{
+#if defined(sun)
+
+ os_id_ = OS_SUN; // set family
+
+ char Buf [32];
+
+ ::memset(Buf,0,sizeof(Buf));
+
+ ACE_OS::sysinfo (SI_RELEASE , Buf, sizeof(Buf)-1);
+
+ if (ACE_OS_String::strcasecmp (Buf , "5.6") == 0)
+ os_id_ = OS_SUN_56;
+ else if (ACE_OS_String::strcasecmp (Buf , "5.7") == 0)
+ os_id_ = OS_SUN_57;
+ else if (ACE_OS_String::strcasecmp (Buf , "5.8") == 0)
+ os_id_ = OS_SUN_58;
+
+#elif defined(HPUX)
+
+ os_id_ = OS_HPUX; // set family
+ // do the same
+
+//#else defined (LINUX, __FreeBSD__ ...)
+//setup here os_id_
+#endif
+}
+
+ACE_POSIX_Proactor::~ACE_POSIX_Proactor (void)
+{
+ this->close ();
+}
+
+int
+ACE_POSIX_Proactor::close (void)
+{
+ return 0;
+}
+
+int
+ACE_POSIX_Proactor::register_handle (ACE_HANDLE handle,
+ const void *completion_key)
+{
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (completion_key);
+ return 0;
+}
+
+int
+ACE_POSIX_Proactor::wake_up_dispatch_threads (void)
+{
+ return 0;
+}
+
+int
+ACE_POSIX_Proactor::close_dispatch_threads (int)
+{
+ return 0;
+}
+
+size_t
+ACE_POSIX_Proactor::number_of_threads (void) const
+{
+ // @@ Implement it.
+ ACE_NOTSUP_RETURN (0);
+}
+
+void
+ACE_POSIX_Proactor::number_of_threads (size_t threads)
+{
+ // @@ Implement it.
+ ACE_UNUSED_ARG (threads);
+}
+
+ACE_HANDLE
+ACE_POSIX_Proactor::get_handle (void) const
+{
+ return ACE_INVALID_HANDLE;
+}
+
+ACE_Asynch_Read_Stream_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Read_Stream_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Stream_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Write_Stream_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Read_File_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_File_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Write_File_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_File_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event ,
+ int priority ,
+ int signal_number)
+{
+ ACE_Asynch_Read_Dgram_Result_Impl *implementation=0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Read_Dgram_Result(handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ flags,
+ protocol_family,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority ,
+ int signal_number)
+{
+ ACE_Asynch_Write_Dgram_Result_Impl *implementation=0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Write_Dgram_Result(handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Accept_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Accept_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Accept_Result (handler,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Transmit_File_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Transmit_File_Result (handler,
+ socket,
+ file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Result_Impl *
+ACE_POSIX_Proactor::create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Timer (handler,
+ act,
+ tv,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+#if 0
+int
+ACE_POSIX_Proactor::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ // Perform a non-blocking "poll" for all the I/O events that have
+ // completed in the I/O completion queue.
+
+ ACE_Time_Value timeout (0, 0);
+ int result = 0;
+
+ for (;;)
+ {
+ result = this->handle_events (timeout);
+ if (result != 0 || errno == ETIME)
+ break;
+ }
+
+ // If our handle_events failed, we'll report a failure to the
+ // Reactor.
+ return result == -1 ? -1 : 0;
+}
+
+int
+ACE_POSIX_Proactor::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask)
+{
+ ACE_UNUSED_ARG (close_mask);
+ ACE_UNUSED_ARG (handle);
+
+ return this->close ();
+}
+#endif /* 0 */
+
+void
+ACE_POSIX_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void */* completion_key*/,
+ u_long error)
+{
+ ACE_SEH_TRY
+ {
+ // Call completion hook
+ asynch_result->complete (bytes_transferred,
+ success,
+ 0, // No completion key.
+ error);
+ }
+ ACE_SEH_FINALLY
+ {
+ // This is crucial to prevent memory leaks
+ delete asynch_result;
+ }
+}
+
+int
+ACE_POSIX_Proactor::post_wakeup_completions (int how_many)
+{
+ ACE_POSIX_Wakeup_Completion *wakeup_completion = 0;
+
+ for (ssize_t ci = 0; ci < how_many; ci++)
+ {
+ ACE_NEW_RETURN (wakeup_completion,
+ ACE_POSIX_Wakeup_Completion (this->wakeup_handler_),
+ -1);
+
+ if (wakeup_completion->post_completion (this) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+class ACE_Export ACE_AIOCB_Notify_Pipe_Manager : public ACE_Handler
+{
+ // = TITLE
+ // This class manages the notify pipe of the AIOCB
+ // Proactor. This class acts as the Handler for the
+ // <Asynch_Read> operations issued on the notify pipe. This
+ // class is very useful in implementing <Asynch_Accept> operation
+ // class for the <AIOCB_Proactor>. This is also useful for
+ // implementing <post_completion> for <AIOCB_Proactor>.
+ //
+ // = DESCRIPTION
+ // <AIOCB_Proactor> class issues a <Asynch_Read> on
+ // the pipe, using this class as the
+ // Handler. <POSIX_Asynch_Result *>'s are sent through the
+ // notify pipe. When <POSIX_Asynch_Result *>'s show up on the
+ // notify pipe, the <POSIX_AIOCB_Proactor> dispatches the
+ // completion of the <Asynch_Read_Stream> and calls the
+ // <handle_read_stream> of this class. This class calls
+ // <complete> on the <POSIX_Asynch_Result *> and thus calls the
+ // application handler.
+ // Handling the MessageBlock:
+ // We give this message block to read the result pointer through
+ // the notify pipe. We expect that to read 4 bytes from the
+ // notify pipe, for each <accept> call. Before giving this
+ // message block to another <accept>, we update <wr_ptr> and put
+ // it in its initial position.
+public:
+ ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
+ // Constructor. You need the posix proactor because you need to call
+ // <application_specific_code>
+
+ virtual ~ACE_AIOCB_Notify_Pipe_Manager (void);
+ // Destructor.
+
+ int notify ();
+ // Send the result pointer through the notification pipe.
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is the call back method when <Asynch_Read> from the pipe is
+ // complete.
+
+private:
+ ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_;
+ // The implementation proactor class.
+
+ ACE_Message_Block message_block_;
+ // Message block to get ACE_POSIX_Asynch_Result pointer from the
+ // pipe.
+
+ ACE_Pipe pipe_;
+ // Pipe for the communication between Proactor and the
+ // Asynch_Accept.
+
+ ACE_POSIX_AIOCB_Asynch_Read_Stream read_stream_;
+ // To do asynch_read on the pipe.
+
+ ACE_AIOCB_Notify_Pipe_Manager (void);
+ // Default constructor. Shouldnt be called.
+};
+
+ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
+ : posix_aiocb_proactor_ (posix_aiocb_proactor),
+ message_block_ (sizeof (ACE_POSIX_Asynch_Accept_Result *)),
+ read_stream_ (posix_aiocb_proactor)
+{
+ // Open the pipe.
+ this->pipe_.open ();
+
+ // Set write side in NONBLOCK mode
+ ACE::set_flags (this->pipe_.write_handle (), ACE_NONBLOCK);
+
+ // Let AIOCB_Proactor know about our handle
+ posix_aiocb_proactor_->set_notify_handle (this->pipe_.read_handle ());
+
+ // Open the read stream.
+ if (this->read_stream_.open (*this,
+ this->pipe_.read_handle (),
+ 0, // Completion Key
+ 0) // Proactor
+ == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:%p\n",
+ "ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:"
+ "Open on Read Stream failed"));
+
+ // Issue an asynch_read on the read_stream of the notify pipe.
+ if (this->read_stream_.read (this->message_block_,
+ 1, // enough to read 1 byte
+ 0, // ACT
+ 0) // Priority
+ == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:%p\n",
+ "ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:"
+ "Read from pipe failed"));
+}
+
+ACE_AIOCB_Notify_Pipe_Manager::~ACE_AIOCB_Notify_Pipe_Manager (void)
+{
+}
+
+int
+ACE_AIOCB_Notify_Pipe_Manager::notify ()
+{
+ // Send the result pointer through the pipe.
+ char char_send = 0;
+ int ret_val = ACE::send (this->pipe_.write_handle (),
+ & char_send ,
+ sizeof (char_send));
+
+ if (ret_val < 0 && errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P %t):%p\n",
+ "ACE_AIOCB_Notify_Pipe_Manager::notify"
+ "Error:Writing on to notify pipe failed"),
+ -1);
+ return 0;
+}
+
+void
+ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result & /*result*/)
+{
+ // 1. Start new read to avoid pipe overflow
+
+ // Set the message block properly. Put the <wr_ptr> back in the
+ // initial position.
+ if (this->message_block_.length () > 0)
+ this->message_block_.wr_ptr (this->message_block_.rd_ptr ());
+
+ // One accept has completed. Issue a read to handle any
+ // <post_completion>s in the future.
+ if (this->read_stream_.read (this->message_block_,
+ 1, // enough to read 1 byte
+ 0, // ACT
+ 0) // Priority
+ == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t):%p\n",
+ "ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream:"
+ "Read from pipe failed"));
+
+
+ // 2. Do the upcalls
+ // this->posix_aiocb_proactor_->process_result_queue ();
+}
+
+// Public constructor for common use.
+ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations)
+ : aiocb_notify_pipe_manager_ (0),
+ aiocb_list_ (0),
+ result_list_ (0),
+ aiocb_list_max_size_ (max_aio_operations),
+ aiocb_list_cur_size_ (0),
+ notify_pipe_read_handle_ (ACE_INVALID_HANDLE),
+ num_deferred_aiocb_ (0),
+ num_started_aio_ (0)
+{
+ //check for correct value for max_aio_operations
+ check_max_aio_num ();
+
+ ACE_NEW (aiocb_list_,
+ aiocb *[aiocb_list_max_size_]);
+ ACE_NEW (result_list_,
+ ACE_POSIX_Asynch_Result *[aiocb_list_max_size_]);
+
+ // Initialize the array.
+ for (size_t ai = 0; ai < this->aiocb_list_max_size_; ai++)
+ {
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ }
+
+ create_notify_manager ();
+}
+
+// Special protected constructor for ACE_SUN_Proactor
+ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations,
+ ACE_POSIX_Proactor::Proactor_Type ptype)
+ : aiocb_notify_pipe_manager_ (0),
+ aiocb_list_ (0),
+ result_list_ (0),
+ aiocb_list_max_size_ (max_aio_operations),
+ aiocb_list_cur_size_ (0),
+ notify_pipe_read_handle_ (ACE_INVALID_HANDLE),
+ num_deferred_aiocb_ (0),
+ num_started_aio_ (0)
+{
+ ACE_UNUSED_ARG (ptype);
+
+ //check for correct value for max_aio_operations
+ check_max_aio_num ();
+
+ ACE_NEW (aiocb_list_,
+ aiocb *[aiocb_list_max_size_]);
+ ACE_NEW (result_list_,
+ ACE_POSIX_Asynch_Result *[aiocb_list_max_size_]);
+
+ // Initialize the array.
+ for (size_t ai = 0; ai < this->aiocb_list_max_size_; ai++)
+ {
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ }
+
+ // @@ We should create Notify_Pipe_Manager in the derived class to
+ // provide correct calls for virtual functions !!!
+}
+
+// Destructor.
+ACE_POSIX_AIOCB_Proactor::~ACE_POSIX_AIOCB_Proactor (void)
+{
+ delete_notify_manager ();
+
+ // delete all uncomlpeted operarion
+ // as nobody will notify client since now
+ for (size_t ai = 0; ai < aiocb_list_max_size_; ai++)
+ {
+ delete result_list_[ai];
+ result_list_[ai] = 0;
+ aiocb_list_[ai] = 0;
+ }
+
+ delete [] aiocb_list_;
+ aiocb_list_ = 0;
+
+ delete [] result_list_;
+ result_list_ = 0;
+
+ clear_result_queue ();
+}
+
+void ACE_POSIX_AIOCB_Proactor::set_notify_handle (ACE_HANDLE h)
+{
+ notify_pipe_read_handle_ = h;
+}
+
+void ACE_POSIX_AIOCB_Proactor::check_max_aio_num ()
+{
+ long max_os_aio_num = ACE_OS ::sysconf (_SC_AIO_MAX);
+
+ // Define max limit AIO's for concrete OS
+ // -1 means that there is no limit, but it is not true
+ // (example, SunOS 5.6)
+
+ if (max_os_aio_num > 0
+ && aiocb_list_max_size_ > (unsigned long) max_os_aio_num
+ )
+ aiocb_list_max_size_ = max_os_aio_num;
+
+#if defined (HPUX)
+ // Although HPUX 11.00 allows to start 2048 AIO's
+ // for all process in system
+ // it has a limit 256 max elements for aio_suspend ()
+ // It is a pity, but ...
+
+ long max_os_listio_num = ACE_OS ::sysconf (_SC_AIO_LISTIO_MAX);
+ if (max_os_listio_num > 0
+ && aiocb_list_max_size_ > (unsigned long) max_os_listio_num)
+ aiocb_list_max_size_ = max_os_listio_num;
+#endif /* HPUX */
+
+ // check for user-defined value
+ // ACE_AIO_MAX_SIZE if defined in POSIX_Proactor.h
+
+ if (aiocb_list_max_size_ <= 0
+ || aiocb_list_max_size_ > ACE_AIO_MAX_SIZE)
+ aiocb_list_max_size_ = ACE_AIO_MAX_SIZE;
+
+ // check for max number files to open
+
+ int max_num_files = ACE::max_handles ();
+
+ if (max_num_files > 0
+ && aiocb_list_max_size_ > (unsigned long) max_num_files)
+ {
+ ACE::set_handle_limit (aiocb_list_max_size_);
+
+ max_num_files = ACE::max_handles ();
+ }
+
+ if (max_num_files > 0
+ && aiocb_list_max_size_ > (unsigned long) max_num_files)
+ aiocb_list_max_size_ = (unsigned long) max_num_files;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P | %t) ACE_POSIX_AIOCB_Proactor::Max Number of AIOs=%d\n",
+ aiocb_list_max_size_));
+
+}
+
+void
+ACE_POSIX_AIOCB_Proactor::create_notify_manager (void)
+{
+ // Accept Handler for aio_accept. Remember! this issues a Asynch_Read
+ // on the notify pipe for doing the Asynch_Accept.
+
+ if (aiocb_notify_pipe_manager_ == 0)
+ ACE_NEW (aiocb_notify_pipe_manager_,
+ ACE_AIOCB_Notify_Pipe_Manager (this));
+}
+
+void
+ACE_POSIX_AIOCB_Proactor::delete_notify_manager (void)
+{
+ // We are responsible for delete as all pointers set to 0 after
+ // delete, it is save to delete twice
+
+ delete aiocb_notify_pipe_manager_;
+ aiocb_notify_pipe_manager_ = 0;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::handle_events (ACE_Time_Value &wait_time)
+{
+ // Decrement <wait_time> with the amount of time spent in the method
+ ACE_Countdown_Time countdown (&wait_time);
+ return this->handle_events (wait_time.msec ());
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::handle_events (void)
+{
+ return this->handle_events (ACE_INFINITE);
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::notify_completion(int sig_num)
+{
+ ACE_UNUSED_ARG (sig_num);
+
+ return this->aiocb_notify_pipe_manager_->notify ();
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::post_completion (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ int ret_val = this->putq_result (result);
+
+ return ret_val;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::putq_result (ACE_POSIX_Asynch_Result *result)
+{
+ // this protected method should be called with locked mutex_
+ // we can't use GUARD as Proactor uses non-recursive mutex
+
+ if (!result)
+ return -1;
+
+ int sig_num = result->signal_number ();
+ int ret_val = this->result_queue_.enqueue_tail (result);
+
+ if (ret_val == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:ACE_POSIX_AIOCB_Proactor::putq_result failed\n"),
+ -1);
+
+ this->notify_completion (sig_num);
+
+ return 0;
+}
+
+ACE_POSIX_Asynch_Result * ACE_POSIX_AIOCB_Proactor::getq_result (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, 0));
+
+
+ ACE_POSIX_Asynch_Result* result = 0;
+
+ if (this->result_queue_.dequeue_head (result) != 0)
+ return 0;
+
+// don;t waste time if queue is empty - it is normal
+// or check queue size before dequeue_head
+// ACE_ERROR_RETURN ((LM_ERROR,
+// "%N:%l:(%P | %t):%p\n",
+// "ACE_POSIX_AIOCB_Proactor::getq_result failed"),
+// 0);
+
+ return result;
+}
+
+int ACE_POSIX_AIOCB_Proactor::clear_result_queue (void)
+{
+ int ret_val = 0;
+ ACE_POSIX_Asynch_Result* result = 0;
+
+ while ((result = this->getq_result ()) != 0)
+ {
+ delete result;
+ ret_val++;
+ }
+
+ return ret_val;
+}
+
+int ACE_POSIX_AIOCB_Proactor::process_result_queue (void)
+{
+ int ret_val = 0;
+ ACE_POSIX_Asynch_Result* result = 0;
+
+ while ((result = this->getq_result ()) != 0)
+ {
+ this->application_specific_code
+ (result,
+ result->bytes_transferred(), // 0, No bytes transferred.
+ 1, // Result : True.
+ 0, // No completion key.
+ result->error()); //0, No error.
+
+ ret_val++;
+ }
+
+ return ret_val;
+}
+
+ACE_Asynch_Read_Stream_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_read_stream (void)
+{
+ ACE_Asynch_Read_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Read_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Stream_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_write_stream (void)
+{
+ ACE_Asynch_Write_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Write_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Dgram_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_read_dgram (void)
+{
+ ACE_Asynch_Read_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Read_Dgram (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Dgram_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_write_dgram (void)
+{
+ ACE_Asynch_Write_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Write_Dgram (this),
+ 0);
+
+ return implementation;
+}
+
+ACE_Asynch_Read_File_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_read_file (void)
+{
+ ACE_Asynch_Read_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Read_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_File_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_write_file (void)
+{
+ ACE_Asynch_Write_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Write_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Accept_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_accept (void)
+{
+ ACE_Asynch_Accept_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Accept (this),
+ 0);
+ //was ACE_POSIX_AIOCB_Asynch_Accept (this)
+
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Impl *
+ACE_POSIX_AIOCB_Proactor::create_asynch_transmit_file (void)
+{
+ ACE_Asynch_Transmit_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_AIOCB_Asynch_Transmit_File (this),
+ 0);
+ return implementation;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::handle_events (u_long milli_seconds)
+{
+ int result_suspend = 0;
+ int retval= 0;
+
+ if (milli_seconds == ACE_INFINITE)
+ // Indefinite blocking.
+ result_suspend = aio_suspend (aiocb_list_,
+ aiocb_list_max_size_,
+ 0);
+ else
+ {
+ // Block on <aio_suspend> for <milli_seconds>
+ timespec timeout;
+ timeout.tv_sec = milli_seconds / 1000;
+ timeout.tv_nsec = (milli_seconds - (timeout.tv_sec * 1000)) * 1000;
+ result_suspend = aio_suspend (aiocb_list_,
+ aiocb_list_max_size_,
+ &timeout);
+ }
+
+ // Check for errors
+ if (result_suspend == -1)
+ {
+ if (errno != EAGAIN && // Timeout
+ errno != EINTR ) // Interrupted call
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_AIOCB_Proactor::handle_events:"
+ "aio_suspend failed\n"));
+
+ // let continue work
+ // we should check "post_completed" queue
+ }
+ else
+ {
+ size_t index = 0;
+ size_t count = aiocb_list_max_size_; // max number to iterate
+ int error_status = 0;
+ int return_status = 0;
+
+ for (;; retval++)
+ {
+ ACE_POSIX_Asynch_Result *asynch_result =
+ find_completed_aio (error_status,
+ return_status,
+ index,
+ count);
+
+ if (asynch_result == 0)
+ break;
+
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ return_status, // Bytes transferred.
+ 1, // Success
+ 0, // No completion key.
+ error_status); // Error
+ }
+ }
+
+ // process post_completed results
+ retval += this->process_result_queue ();
+
+ return retval > 0 ? 1 : 0;
+}
+
+ACE_POSIX_Asynch_Result *
+ACE_POSIX_AIOCB_Proactor::find_completed_aio (int &error_status,
+ int &return_status,
+ size_t &index,
+ size_t &count)
+{
+ // parameter index defines initial slot to scan
+ // parameter count tells us how many slots should we scan
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, 0));
+
+ ACE_POSIX_Asynch_Result *asynch_result = 0;
+
+ error_status = 0;
+ return_status= 0;
+
+ if (num_started_aio_ == 0) // save time
+ return asynch_result;
+
+
+ for (; count > 0; index++ , count--)
+ {
+ if (index >= aiocb_list_max_size_) // like a wheel
+ index = 0;
+
+ if (aiocb_list_[index] == 0) // Dont process null blocks.
+ continue;
+
+ // Get the error status of the aio_ operation.
+ error_status = aio_error (aiocb_list_[index]);
+
+ if (error_status == -1) // <aio_error> itself has failed.
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_AIOCB_Proactor::find_completed_aio:"
+ "<aio_error> has failed\n"));
+
+ break;
+
+ // we should notify user, otherwise :
+ // memory leak for result and "hanging" user
+ // what was before skip this operation
+
+ //aiocb_list_[index] = 0;
+ //result_list_[index] = 0;
+ //aiocb_list_cur_size_--;
+ //continue;
+ }
+
+ // Continue the loop if <aio_> operation is still in progress.
+ if (error_status != EINPROGRESS)
+ break;
+
+ } // end for
+
+ if (count == 0) // all processed , nothing found
+ return asynch_result;
+
+ if (error_status == ECANCELED)
+ return_status = 0;
+ else if (error_status == -1)
+ return_status = 0;
+ else
+ return_status = aio_return (aiocb_list_[index]);
+
+ if (return_status == -1)
+ {
+ return_status = 0; // zero bytes transferred
+
+ if (error_status == 0) // nonsense
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_AIOCB_Proactor::find_completed_aio:"
+ "<aio_return> failed\n"));
+ }
+
+
+ asynch_result = result_list_[index];
+
+ aiocb_list_[index] = 0;
+ result_list_[index] = 0;
+ aiocb_list_cur_size_--;
+
+ num_started_aio_--; // decrement count active aios
+ index++; // for next iteration
+ count--; // for next iteration
+
+ this->start_deferred_aio ();
+ //make attempt to start deferred AIO
+ //It is safe as we are protected by mutex_
+
+ return asynch_result;
+}
+
+void
+ACE_POSIX_AIOCB_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ ACE_POSIX_Proactor::application_specific_code (asynch_result,
+ bytes_transferred,
+ success,
+ completion_key,
+ error);
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::register_and_start_aio (ACE_POSIX_Asynch_Result *result,
+ int op)
+{
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::register_and_start_aio");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1));
+
+ int ret_val = (aiocb_list_cur_size_ >= aiocb_list_max_size_) ? -1 : 0;
+
+ if (result == 0) // Just check the status of the list
+ return ret_val;
+
+ // Save operation code in the aiocb
+ switch (op)
+ {
+ case 0 :
+ result->aio_lio_opcode = LIO_READ;
+ break;
+
+ case 1 :
+ result->aio_lio_opcode = LIO_WRITE;
+ break;
+
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "register_and_start_aio: Invalid operation code\n"),
+ -1);
+ }
+
+ if (ret_val != 0) // No free slot
+ {
+ errno = EAGAIN;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "register_and_start_aio: "
+ "No space to store the <aio>info\n"),
+ -1);
+ }
+
+ // Find a free slot and store.
+
+ ret_val = allocate_aio_slot (result);
+
+ if (ret_val < 0)
+ return -1;
+
+ size_t index = ACE_static_cast (size_t, ret_val);
+
+ result_list_[index] = result; //Store result ptr anyway
+ aiocb_list_cur_size_++;
+
+ ret_val = start_aio (result);
+
+ switch (ret_val)
+ {
+ case 0 : // started OK
+ aiocb_list_[index] = result;
+ return 0;
+
+ case 1 : //OS AIO queue overflow
+ num_deferred_aiocb_ ++;
+ return 0;
+
+ default: //Invalid request, there is no point
+ break; // to start it later
+ }
+
+ result_list_[index] = 0;
+ aiocb_list_cur_size_--;
+
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "register_and_start_aio: Invalid request to start <aio>\n"));
+ return -1;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result *result)
+{
+ size_t i = 0;
+
+ // we reserve zero slot for ACE_AIOCB_Notify_Pipe_Manager
+ // so make check for ACE_AIOCB_Notify_Pipe_Manager request
+
+ if (notify_pipe_read_handle_ == result->aio_fildes) // Notify_Pipe ?
+ { // should be free,
+ if (result_list_[i] != 0) // only 1 request
+ { // is allowed
+ errno = EAGAIN;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
+ "internal Proactor error 0\n"),
+ -1);
+ }
+ }
+ else //try to find free slot as usual, but starting from 1
+ {
+ for (i= 1; i < this->aiocb_list_max_size_; i++)
+ if (result_list_[i] == 0)
+ break;
+ }
+
+ if (i >= this->aiocb_list_max_size_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
+ "internal Proactor error 1\n"),
+ -1);
+
+
+ //setup OS notification methods for this aio
+ result->aio_sigevent.sigev_notify = SIGEV_NONE;
+
+ return ACE_static_cast (int, i);
+}
+
+// start_aio has new return codes
+// 0 AIO was started successfully
+// 1 AIO was not started, OS AIO queue overflow
+// -1 AIO was not started, other errors
+
+int
+ACE_POSIX_AIOCB_Proactor::start_aio (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio");
+
+ int ret_val;
+ const ACE_TCHAR *ptype;
+
+ // Start IO
+
+ switch (result->aio_lio_opcode )
+ {
+ case LIO_READ :
+ ptype = "read ";
+ ret_val = aio_read (result);
+ break;
+ case LIO_WRITE :
+ ptype = "write";
+ ret_val = aio_write (result);
+ break;
+ default:
+ ptype = "?????";
+ ret_val = -1;
+ break;
+ }
+
+ if (ret_val == 0)
+ num_started_aio_ ++;
+ else // if (ret_val == -1)
+ {
+ if (errno == EAGAIN) //Ok, it will be deferred AIO
+ ret_val = 1;
+ else
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::start_aio: aio_%s %p\n",
+ ptype,
+ "queueing failed\n"));
+ }
+
+ return ret_val;
+}
+
+
+int
+ACE_POSIX_AIOCB_Proactor::start_deferred_aio ()
+{
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_deferred_aio");
+
+ // This protected method is called from
+ // find_completed_aio after any AIO completion
+ // We should call this method always with locked
+ // ACE_POSIX_AIOCB_Proactor::mutex_
+ //
+ // It tries to start the first deferred AIO
+ // if such exists
+
+ if (num_deferred_aiocb_ == 0)
+ return 0; // nothing to do
+
+ size_t i = 0;
+
+ for (i= 0; i < this->aiocb_list_max_size_; i++)
+ if (result_list_[i] !=0 // check for
+ && aiocb_list_[i] ==0) // deferred AIO
+ break;
+
+ if (i >= this->aiocb_list_max_size_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "start_deferred_aio:"
+ "internal Proactor error 3\n"),
+ -1);
+
+ ACE_POSIX_Asynch_Result *result = result_list_[i];
+
+ int ret_val = start_aio (result);
+
+ switch (ret_val)
+ {
+ case 0 : //started OK , decrement count of deferred AIOs
+ aiocb_list_[i] = result;
+ num_deferred_aiocb_ --;
+ return 0;
+
+ case 1 :
+ return 0; //try again later
+
+ default : // Invalid Parameters , should never be
+ break;
+ }
+
+ //AL notify user
+
+ result_list_[i] = 0;
+ aiocb_list_cur_size_--;
+
+ num_deferred_aiocb_ --;
+
+ result->set_error (errno);
+ result->set_bytes_transferred (0);
+ this->putq_result (result); // we are with locked mutex_ here !
+
+ return -1;
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::cancel_aio (ACE_HANDLE handle)
+{
+ // This new method should be called from
+ // ACE_POSIX_Asynch_Operation instead of usual ::aio_cancel
+ // It scans the result_list_ and defines all AIO requests
+ // that were issued for handle "handle"
+ //
+ // For all deferred AIO requests with handle "handle"
+ // it removes its from the lists and notifies user
+ //
+ // For all running AIO requests with handle "handle"
+ // it calls ::aio_cancel. According to the POSIX standards
+ // we will receive ECANCELED for all ::aio_canceled AIO requests
+ // later on return from ::aio_suspend
+
+ ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::cancel_aio");
+
+ int num_total = 0;
+ int num_cancelled = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1));
+
+ size_t ai = 0;
+
+ for (ai = 0; ai < aiocb_list_max_size_; ai++)
+ {
+ if (result_list_[ai] == 0) //skip empty slot
+ continue;
+
+ if (result_list_[ai]->aio_fildes != handle) //skip not our slot
+ continue;
+
+ num_total++;
+
+ ACE_POSIX_Asynch_Result *asynch_result = result_list_[ai];
+
+ if (aiocb_list_ [ai] == 0) //deferred aio
+ {
+ num_cancelled ++;
+ num_deferred_aiocb_ --;
+
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ aiocb_list_cur_size_--;
+
+ asynch_result->set_error (ECANCELED);
+ asynch_result->set_bytes_transferred (0);
+ this->putq_result (asynch_result);
+ // we are with locked mutex_ here !
+ }
+ else //cancel started aio
+ {
+ int rc_cancel = this->cancel_aiocb (asynch_result);
+
+ if (rc_cancel == 0) //notification in the future
+ num_cancelled ++; //it is OS responsiblity
+ }
+ }
+
+ } // release mutex_
+
+ if (num_total == 0)
+ return 1; // ALLDONE
+
+ if (num_cancelled == num_total)
+ return 0; // CANCELLED
+
+ return 2; // NOT CANCELLED
+}
+
+int
+ACE_POSIX_AIOCB_Proactor::cancel_aiocb (ACE_POSIX_Asynch_Result * result)
+{
+ // This new method is called from cancel_aio
+ // to cancel concrete running AIO request
+ int rc = ::aio_cancel (0, result);
+
+ // Check the return value and return 0/1/2 appropriately.
+ if (rc == AIO_CANCELED)
+ return 0;
+ else if (rc == AIO_ALLDONE)
+ return 1;
+ else if (rc == AIO_NOTCANCELED)
+ return 2;
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "cancel_aiocb:"
+ "Unexpected result from <aio_cancel>"),
+ -1);
+
+}
+
+
+// *********************************************************************
+
+ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (size_t max_aio_operations)
+ : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
+ ACE_POSIX_Proactor::PROACTOR_SIG)
+{
+ // = Set up the mask we'll use to block waiting for SIGRTMIN. Use that
+ // to add it to the signal mask for this thread, and also set the process
+ // signal action to pass signal information when we want it.
+
+ // Clear the signal set.
+ if (sigemptyset (&this->RT_completion_signals_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:%p\n",
+ "Couldn't init the RT completion signal set"));
+
+ // Add the signal number to the signal set.
+ if (sigaddset (&this->RT_completion_signals_, ACE_SIGRTMIN) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:%p\n",
+ "Couldnt init the RT completion signal set"));
+ this->mask_signals (&this->RT_completion_signals_);
+ // Set up the signal action for SIGRTMIN.
+ this->setup_signal_handler (ACE_SIGRTMIN);
+
+ // we do not have to create notify manager
+ return;
+}
+
+ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (const sigset_t signal_set,
+ size_t max_aio_operations)
+ : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
+ ACE_POSIX_Proactor::PROACTOR_SIG)
+{
+ // = Keep <Signal_set> with the Proactor, mask all the signals and
+ // setup signal actions for the signals in the <signal_set>.
+
+ // = Keep <signal_set> with the Proactor.
+
+ // Empty the signal set first.
+ if (sigemptyset (&this->RT_completion_signals_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "sigemptyset failed"));
+
+ // For each signal number present in the <signal_set>, add it to
+ // the signal set we use, and also set up its process signal action
+ // to allow signal info to be passed into sigwait/sigtimedwait.
+ int member = 0;
+ for (int si = ACE_SIGRTMIN; si <= ACE_SIGRTMAX; si++)
+ {
+ member = sigismember (&signal_set,
+ si);
+ if (member == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor:"
+ "sigismember failed"));
+ else if (member == 1)
+ {
+ sigaddset (&this->RT_completion_signals_, si);
+ this->setup_signal_handler (si);
+ }
+ }
+
+ // Mask all the signals.
+ this->mask_signals (&this->RT_completion_signals_);
+
+ // we do not have to create notify manager
+ return;
+}
+
+ACE_POSIX_SIG_Proactor::~ACE_POSIX_SIG_Proactor (void)
+{
+ // @@ Enable the masked signals again.
+}
+
+int
+ACE_POSIX_SIG_Proactor::handle_events (ACE_Time_Value &wait_time)
+{
+ // Decrement <wait_time> with the amount of time spent in the method
+ ACE_Countdown_Time countdown (&wait_time);
+ return this->handle_events (wait_time.msec ());
+}
+
+int
+ACE_POSIX_SIG_Proactor::handle_events (void)
+{
+ return this->handle_events (ACE_INFINITE);
+}
+
+int
+ACE_POSIX_SIG_Proactor::notify_completion (int sig_num)
+{
+ // Get this process id.
+ pid_t pid = ACE_OS::getpid ();
+ if (pid == (pid_t) -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%N:%l(%P | %t):%p",
+ "<getpid> failed"),
+ -1);
+
+ // Set the signal information.
+ sigval value;
+#if defined (__FreeBSD__)
+ value.sigval_int = -1;
+#else
+ value.sival_int = -1;
+#endif /* __FreeBSD__ */
+
+ // Solaris 8 can "forget" to delivery
+ // two or more signals queued immediately.
+ // Just comment the following "if" statement
+ // and try this->post_completion(2)
+
+ if (os_id_ == OS_SUN_58 && result_queue_.size() > 1)
+ return 0;
+
+ // Queue the signal.
+ if (sigqueue (pid, sig_num, value) == 0)
+ return 0;
+
+ if (errno != EAGAIN)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%N:%l:(%P | %t):%p\n",
+ "<sigqueue> failed"),
+ -1);
+ return -1;
+}
+
+ACE_Asynch_Result_Impl *
+ACE_POSIX_SIG_Proactor::create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ int is_member = 0;
+
+ // Fix the signal number.
+ if (signal_number == -1)
+ {
+ int si;
+ for (si = ACE_SIGRTMAX;
+ (is_member == 0) && (si >= ACE_SIGRTMIN);
+ si--)
+ {
+ is_member = sigismember (&this->RT_completion_signals_,
+ si);
+ if (is_member == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::%s\n",
+ "ACE_POSIX_SIG_Proactor::create_asynch_timer:"
+ "sigismember failed"),
+ 0);
+ }
+
+ if (is_member == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%N:%l:(%P | %t)::%s\n",
+ "ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor:"
+ "Signal mask set empty"),
+ 0);
+ else
+ // + 1 to nullify loop increment.
+ signal_number = si + 1;
+ }
+
+ ACE_Asynch_Result_Impl *implementation;
+ ACE_NEW_RETURN (implementation,
+ ACE_POSIX_Asynch_Timer (handler,
+ act,
+ tv,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+
+void sig_handler (int sig_num, siginfo_t *, ucontext_t *)
+{
+ // Should never be called
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:(%P | %t)::sig_handler received signal: %d\n",
+ sig_num));
+ return;
+}
+
+int
+ACE_POSIX_SIG_Proactor::setup_signal_handler (int signal_number) const
+{
+ // Set up the specified signal so that signal information will be
+ // passed to sigwaitinfo/sigtimedwait. Don't change the default
+ // signal handler - having a handler and waiting for the signal can
+ // produce undefined behavior.
+
+ // But can not use SIG_DFL
+ // With SIG_DFL after delivering the first signal
+ // SIG_DFL handler resets SA_SIGINFO flags
+ // and we will lose all information sig_info
+ // At least all SunOS have such behavior
+
+ struct sigaction reaction;
+ sigemptyset (&reaction.sa_mask); // Nothing else to mask.
+ reaction.sa_flags = SA_SIGINFO; // Realtime flag.
+ reaction.sa_sigaction = ACE_SIGNAL_C_FUNC(sig_handler); // (SIG_DFL);
+ int sigaction_return = ACE_OS::sigaction (signal_number,
+ &reaction,
+ 0);
+ if (sigaction_return == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%p\n",
+ "Proactor couldnt do sigaction for the RT SIGNAL"),
+ -1);
+ return 0;
+}
+
+
+int
+ACE_POSIX_SIG_Proactor::mask_signals (const sigset_t *signals) const
+{
+ if (ACE_OS::pthread_sigmask (SIG_BLOCK, signals, 0) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "pthread_sigmask failed"),
+ -1);
+ return 0;
+}
+
+int
+ACE_POSIX_SIG_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result *result)
+{
+ size_t i = 0;
+
+ //try to find free slot as usual, starting from 0
+ for (i = 0; i < this->aiocb_list_max_size_; i++)
+ if (result_list_[i] == 0)
+ break;
+
+ if (i >= this->aiocb_list_max_size_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::\n"
+ "ACE_POSIX_SIG_Proactor::allocate_aio_slot "
+ "internal Proactor error 1\n"),
+ -1);
+
+ int retval = ACE_static_cast (int, i);
+
+ // setup OS notification methods for this aio
+ // store index!!, not pointer in signal info
+ result->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ result->aio_sigevent.sigev_signo = result->signal_number ();
+#if defined (__FreeBSD__)
+ result->aio_sigevent.sigev_value.sigval_int = retval;
+#else
+ result->aio_sigevent.sigev_value.sival_int = retval;
+#endif /* __FreeBSD__ */
+
+ return retval;
+}
+
+int
+ACE_POSIX_SIG_Proactor::handle_events (unsigned long milli_seconds)
+{
+ int result_sigwait = 0;
+ siginfo_t sig_info;
+
+ // Mask all the signals.
+ if (this->mask_signals (&this->RT_completion_signals_) != 0)
+ return -1;
+
+ // Wait for the signals.
+ if (milli_seconds == ACE_INFINITE)
+ {
+ result_sigwait = sigwaitinfo (&this->RT_completion_signals_,
+ &sig_info);
+ }
+ else
+ {
+ // Wait for <milli_seconds> amount of time.
+ timespec timeout;
+ timeout.tv_sec = milli_seconds / 1000;
+ timeout.tv_nsec = (milli_seconds - (timeout.tv_sec * 1000)) * 1000;
+ result_sigwait = sigtimedwait (&this->RT_completion_signals_,
+ &sig_info,
+ &timeout);
+ }
+
+ size_t index = 0; // start index to scan aiocb list
+ size_t count = aiocb_list_max_size_; // max number to iterate
+ int error_status = 0;
+ int return_status = 0;
+ int flg_aio = 0; // 1 if AIO Completion possible
+ int flg_que = 0; // 1 if SIGQUEUE possible
+
+ // define index to start
+ // nothing will happen if it contains garbage
+#if defined (__FreeBSD__)
+ index = ACE_static_cast (size_t, sig_info.si_value.sigval_int);
+#else
+ index = ACE_static_cast (size_t, sig_info.si_value.sival_int);
+#endif
+
+ // Check for errors
+ // but let continue work in case of errors
+ // we should check "post_completed" queue
+ if (result_sigwait == -1)
+ {
+ if (errno != EAGAIN && // timeout
+ errno != EINTR ) // interrupted system call
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_POSIX_SIG_Proactor::handle_events:"
+ "sigtimedwait/sigwaitinfo failed"
+ ));
+ }
+ else if (sig_info.si_signo != result_sigwait)
+ {
+ // No errors, RT compleion signal is received.
+ // Is the signo returned consistent with the sig info?
+ ACE_ERROR ((LM_ERROR,
+ "Error:%N:%l:(%P | %t):"
+ "ACE_POSIX_SIG_Proactor::handle_events:"
+ "Inconsistent signal number (%d) in the signal info block",
+ sig_info.si_signo
+ ));
+ }
+ else if (sig_info.si_code == SI_ASYNCIO)
+ flg_aio = 1; // AIO signal received
+ else if (sig_info.si_code == SI_QUEUE)
+ flg_que = 1; // SIGQUEUE received
+ else
+ {
+ // Unknown signal code.
+ // may some other third-party libraries could send it
+ // or message queue could also generate it !
+ // So print the message and check our completions
+ ACE_ERROR ((LM_DEBUG,
+ "%N:%l:(%P | %t):"
+ "ACE_POSIX_SIG_Proactor::handle_events:\n"
+ "Unexpected signal code (%d) returned on completion querying\n",
+ sig_info.si_code));
+ }
+
+ // extra actions for different systems
+ if (os_id_ == OS_SUN_58) // Solaris 8
+ {
+ // Solaris 8 never loses any AIO completion It can store more
+ // than 40000 notifications! So don't waste time to scan all
+ // aiocb list We know exactly what finished in case SI_ASYNCHIO
+
+ // But we can easy have lost SI_QUEUE
+
+ if (flg_aio) // AIO - correct behavior
+ count = 1;
+ flg_que=1; // not to miss "post_completed" results
+ }
+ else if (os_id_ == OS_SUN_56) // Solaris 6
+ {
+ // 1. Solaris 6 always loses any RT signal,
+ // if it has more SIGQUEMAX=32 pending signals
+ // so we should scan the whole aiocb list
+ // 2. Moreover,it has one more bad habit
+ // to notify aio completion
+ // with SI_QUEUE code instead of SI_ASYNCIO.
+
+ // this is reliable solution
+ flg_aio =1; // always find_completed_aio
+ flg_que =1; // always scan queue
+ count = aiocb_list_max_size_;
+ }
+ else // insert here specific for other systems
+ {
+ // this is reliable solution
+ flg_aio =1; // always find_completed_aio
+ flg_que =1; // always scan queue
+ count = aiocb_list_max_size_;
+ }
+
+ // At this point we have
+ // if (flg_aio)
+ // scan aiocb list starting with "index" slot
+ // no more "count" times
+ // till we have no more AIO completed
+ // if (flg_que)
+ // check "post_completed" queue
+
+ int ret_aio = 0;
+ int ret_que = 0;
+
+ if (flg_aio)
+ for (;; ret_aio++)
+ {
+ ACE_POSIX_Asynch_Result *asynch_result =
+ find_completed_aio (error_status,
+ return_status,
+ index,
+ count);
+
+ if (asynch_result == 0)
+ break;
+
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ return_status, // Bytes transferred.
+ 1, // Success
+ 0, // No completion key.
+ error_status); // Error
+ }
+
+ // process post_completed results
+ if (flg_que)
+ ret_que = this->process_result_queue ();
+
+ // Uncomment this if you want to test
+ // and research the behavior of you system
+ // ACE_DEBUG ((LM_DEBUG,
+ // "(%t) NumAIO=%d NumQueue=%d\n",
+ // ret_aio, ret_que));
+
+ return ret_aio + ret_que > 0 ? 1 : 0;
+}
+
+// *********************************************************************
+
+ACE_POSIX_Asynch_Timer::ACE_POSIX_Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number),
+ time_ (tv)
+{
+}
+
+void
+ACE_POSIX_Asynch_Timer::complete (u_long /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ this->handler_.handle_time_out (this->time_, this->act ());
+}
+
+// *********************************************************************
+
+ACE_POSIX_Wakeup_Completion::ACE_POSIX_Wakeup_Completion (ACE_Handler &handler,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_POSIX_Asynch_Result (handler, act, event, 0, 0, priority, signal_number)
+{
+}
+
+ACE_POSIX_Wakeup_Completion::~ACE_POSIX_Wakeup_Completion (void)
+{
+}
+
+void
+ACE_POSIX_Wakeup_Completion::complete (u_long /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+
+ this->handler_.handle_wakeup ();
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Unbounded_Queue<ACE_POSIX_Asynch_Result *>;
+template class ACE_Node<ACE_POSIX_Asynch_Result *>;
+template class ACE_Unbounded_Queue_Iterator<ACE_POSIX_Asynch_Result *>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Unbounded_Queue<ACE_POSIX_Asynch_Result *>
+#pragma instantiate ACE_Node<ACE_POSIX_Asynch_Result *>
+#pragma instantiate ACE_Unbounded_Queue_Iterator<ACE_POSIX_Asynch_Result *>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+#endif /* ACE_HAS_AIO_CALLS */
diff --git a/ace/Demux/POSIX_Proactor.h b/ace/Demux/POSIX_Proactor.h
new file mode 100644
index 00000000000..939157e5d2d
--- /dev/null
+++ b/ace/Demux/POSIX_Proactor.h
@@ -0,0 +1,589 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file POSIX_Proactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ * @author Alexander Libman <alibman@baltimore.com>
+ */
+//=============================================================================
+
+#ifndef ACE_POSIX_PROACTOR_H
+#define ACE_POSIX_PROACTOR_H
+
+#include "ace/Proactor_Impl.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+// POSIX implementation of Proactor depends on the <aio_> family of
+// system calls.
+
+#include "ace/Free_List.h"
+#include "ace/Pipe.h"
+#include "ace/POSIX_Asynch_IO.h"
+#include "ace/Unbounded_Queue.h"
+
+#define ACE_AIO_MAX_SIZE 2048
+#define ACE_AIO_DEFAULT_SIZE 1024
+
+/**
+ * @class ACE_POSIX_Proactor
+ *
+ * @brief POSIX implementation of the Proactor.
+ *
+ * There are two different strategies by which Proactor can get
+ * to know the completion of <aio> operations. One is based on
+ * Asynchronous I/O Control Blocks (AIOCB) where a list of
+ * AIOCBs are stored and completion status of the corresponding
+ * operations are queried on them. The other one is based on
+ * POSIX Real Time signals. This class abstracts out the common
+ * code needed for both the strategies. <ACE_AIOCB_Proactor> and
+ * <ACE_SIG_Proactor> specialize this class for each strategy.
+ */
+class ACE_Export ACE_POSIX_Proactor : public ACE_Proactor_Impl
+{
+ /**
+ * For <POSIX_SIG_Asynch_Accept> operation, this handler class does
+ * the actual work, has to register the real-time signal with the
+ * Proactor.
+ */
+ friend class ACE_POSIX_SIG_Asynch_Accept_Handler;
+
+public:
+ enum Proactor_Type
+ {
+ PROACTOR_POSIX = 0, // base class type
+ PROACTOR_AIOCB = 1,
+ PROACTOR_SIG = 2,
+ PROACTOR_SUN = 3
+ };
+
+ enum SystemType // open for future extention
+ {
+ OS_UNDEFINED= 0x0000,
+ OS_WIN = 0x0100, // for future
+ OS_WIN_NT = OS_WIN | 0x0001,
+ OS_WIN_2000 = OS_WIN | 0x0002,
+ OS_SUN = 0x0200, // Sun Solaris family
+ OS_SUN_55 = OS_SUN | 0x0001,
+ OS_SUN_56 = OS_SUN | 0x0002,
+ OS_SUN_57 = OS_SUN | 0x0004,
+ OS_SUN_58 = OS_SUN | 0x0008,
+ OS_HPUX = 0x0400, // HPUX family
+ OS_HPUX_11 = OS_HPUX | 0x0001,
+ OS_LINUX = 0x0800, // Linux family
+ OS_FREEBSD = 0x1000 // FreeBSD family
+ };
+
+ virtual Proactor_Type get_impl_type (void);
+
+ /// Virtual destructor.
+ virtual ~ACE_POSIX_Proactor (void);
+
+ /// Close down the Proactor.
+ virtual int close (void);
+
+ /// This function is a no-op function for Unix systems. Returns 0.
+ virtual int register_handle (ACE_HANDLE handle,
+ const void *completion_key);
+
+ /**
+ * Post a result to the completion port of the Proactor. If errors
+ * occur, the result will be deleted by this method. If successful,
+ * the result will be deleted by the Proactor when the result is
+ * removed from the completion port. Therefore, the result should
+ * have been dynamically allocated and should be orphaned by the
+ * user once this method is called.
+ */
+ virtual int post_completion (ACE_POSIX_Asynch_Result *result) = 0;
+
+ /// @@ This is a no-op on POSIX platforms. Returns 0.
+ int wake_up_dispatch_threads (void);
+
+ /// @@ This is a no-op on POSIX platforms. Returns 0.
+ int close_dispatch_threads (int wait);
+
+ /// @@ This is a no-op on POSIX platforms. Returns 0.
+ size_t number_of_threads (void) const;
+ void number_of_threads (size_t threads);
+
+ /// This is a no-op in POSIX. Returns ACE_INVALID_HANDLE.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ // Methods used to create Asynch_IO_Result objects. We create the right
+ // objects here in these methods.
+
+ virtual ACE_Asynch_Read_Stream_Result_Impl *create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Write_Stream_Result_Impl *create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Read_File_Result_Impl *create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Write_File_Result_Impl *create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void *act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Read_Dgram_Result_Impl *create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Write_Dgram_Result_Impl *create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Accept_Result_Impl *create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ virtual ACE_Asynch_Transmit_File_Result_Impl *create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create a timer result object which can be used with the Timer
+ /// mechanism of the Proactor.
+ virtual ACE_Asynch_Result_Impl *create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+protected:
+ /// Constructor.
+ ACE_POSIX_Proactor (void);
+
+ /**
+ * Protect against structured exceptions caused by user code when
+ * dispatching handles. The <completion_key> is not very useful
+ * compared to <AST> that can be associated each asynchronous
+ * operation. <completion_key> is implemented right now for the
+ * POSIX Proators.
+ */
+ void application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /**
+ * Post <how_many> completions to the completion port so that all
+ * threads can wake up. This is used in conjunction with the
+ * <run_event_loop>.
+ */
+ virtual int post_wakeup_completions (int how_many);
+
+protected:
+ /// Handler to handle the wakeups. This works in conjunction with the
+ /// <ACE_Proactor::run_event_loop>.
+ ACE_Handler wakeup_handler_;
+ int os_id_ ;
+};
+
+// Forward declarations.
+class ACE_AIOCB_Notify_Pipe_Manager;
+
+/**
+ * @class ACE_POSIX_AIOCB_Proactor
+ *
+ * @brief This Proactor makes use of Asynchronous I/O Control Blocks
+ * (AIOCB) to notify/get the completion status of the <aio_>
+ * operations issued.
+ */
+class ACE_Export ACE_POSIX_AIOCB_Proactor : public ACE_POSIX_Proactor
+{
+
+ /// Handler needs to call application specific code.
+ friend class ACE_AIOCB_Notify_Pipe_Manager;
+
+ /// This class does the registering of Asynch Operations with the
+ /// Proactor which is necessary in the AIOCB strategy.
+ friend class ACE_POSIX_AIOCB_Asynch_Operation;
+
+ // friend class ACE_POSIX_AIOCB_Asynch_Accept_Handler; For
+ // <Asynch_Accept> operation class, this helper class takes care of
+ // doing the <Asynch_Accept>.
+
+public:
+ /// Constructor defines max number asynchronous operations
+ /// which can be started at the same time
+ ACE_POSIX_AIOCB_Proactor (size_t nmaxop = ACE_AIO_DEFAULT_SIZE);
+
+ virtual Proactor_Type get_impl_type (void);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_AIOCB_Proactor (void);
+
+ /**
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time);
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (void);
+
+ /// Post a result to the completion port of the Proactor.
+ virtual int post_completion (ACE_POSIX_Asynch_Result *result);
+
+ // = Methods used to create Asynch_IO objects. We create the right
+ // objects here in these methods.
+
+ virtual ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void);
+
+ virtual ACE_Asynch_Write_Stream_Impl *create_asynch_write_stream (void);
+
+ virtual ACE_Asynch_Read_Dgram_Impl *create_asynch_read_dgram (void);
+
+ virtual ACE_Asynch_Write_Dgram_Impl *create_asynch_write_dgram (void);
+
+ virtual ACE_Asynch_Read_File_Impl *create_asynch_read_file (void);
+
+ virtual ACE_Asynch_Write_File_Impl *create_asynch_write_file (void);
+
+ virtual ACE_Asynch_Accept_Impl *create_asynch_accept (void);
+
+ virtual ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void);
+
+ /**
+ * This method should be called from
+ * ACE_POSIX_Asynch_Operation::cancel()
+ * instead of usual ::aio_cancel.
+ * For all deferred AIO requests with handle "h"
+ * it removes its from the lists and notifies user.
+ * For all running AIO requests with handle "h"
+ * it calls ::aio_cancel. According to the POSIX standards
+ * we will receive ECANCELED for all ::aio_canceled AIO requests
+ * later on return from ::aio_suspend
+ */
+ virtual int cancel_aio (ACE_HANDLE h);
+
+protected:
+
+ /// Special constructor for ACE_SUN_Proactor
+ /// and ACE_POSIX_SIG_Proactor
+ ACE_POSIX_AIOCB_Proactor (size_t nmaxop,
+ ACE_POSIX_Proactor::Proactor_Type ptype);
+
+ /// Call these methods from derived class when virtual table is
+ /// built.
+ void create_notify_manager (void);
+ void delete_notify_manager (void);
+
+ /// Define the maximum number of asynchronous I/O requests
+ /// for the current OS
+ void check_max_aio_num (void) ;
+
+ /// To identify requests from Notify_Pipe_Manager
+ void set_notify_handle (ACE_HANDLE h);
+
+ /**
+ * Dispatch a single set of events. If <milli_seconds> elapses
+ * before any events occur, return 0. Return 1 if a completion
+ * dispatched. Return -1 on errors.
+ */
+ virtual int handle_events (u_long milli_seconds);
+
+ /// We will call the base class's application_specific_code from
+ /// here.
+ void application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ virtual int register_and_start_aio (ACE_POSIX_Asynch_Result *result,
+ int op);
+
+ /// Op code now is saved in ACE_POSIX_Asynch_Result
+ virtual int start_aio (ACE_POSIX_Asynch_Result *result);
+
+ /// Start deferred AIO if necessary
+ int start_deferred_aio();
+
+ /// Cancel running or deferred AIO
+ virtual int cancel_aiocb ( ACE_POSIX_Asynch_Result * result );
+
+ /// Extract the results of aio.
+ ACE_POSIX_Asynch_Result *find_completed_aio (int &error_status,
+ int &return_status,
+ size_t &index,
+ size_t &count);
+
+ /// Find free slot to store result and aiocb pointer
+ virtual int allocate_aio_slot (ACE_POSIX_Asynch_Result *result);
+
+
+ /// Notify queue of "post_completed" ACE_POSIX_Asynch_Results
+ /// called from post_completion method
+ virtual int notify_completion ( int sig_num );
+
+ /// Put "post_completed" result into the internal queue
+ int putq_result (ACE_POSIX_Asynch_Result *result);
+
+ /// Get "post_completed" result from the internal queue
+ ACE_POSIX_Asynch_Result * getq_result (void);
+
+ /// Clear the internal results queue
+ int clear_result_queue (void);
+
+ /// Process the internal results queue
+ int process_result_queue (void);
+
+
+ /// This class takes care of doing <accept> when we use
+ /// AIO_CONTROL_BLOCKS strategy.
+ ACE_AIOCB_Notify_Pipe_Manager *aiocb_notify_pipe_manager_;
+
+ /// Use a dynamically allocated array to keep track of all the aio's
+ /// issued currently.
+ aiocb **aiocb_list_;
+ ACE_POSIX_Asynch_Result **result_list_;
+
+ /// To maintain the maximum size of the array (list).
+ size_t aiocb_list_max_size_;
+
+ /// To maintain the current size of the array (list).
+ size_t aiocb_list_cur_size_;
+
+ /// Mutex to protect work with lists.
+ ACE_SYNCH_MUTEX mutex_;
+
+ /// The purpose of this member is only to identify asynchronous request
+ /// from NotifyManager. We will reserve for it always slot 0
+ /// in the list of aiocb's to be sure that don't lose notifications.
+ ACE_HANDLE notify_pipe_read_handle_ ;
+
+ /// number of ACE_POSIX_Asynch_Result's waiting for start
+ /// i.e. deferred AIOs
+ size_t num_deferred_aiocb_ ;
+
+ /// Number active,i.e. running requests
+ size_t num_started_aio_ ;
+
+ /// Queue which keeps "post_completed" ACE_POSIX_Asynch_Result's
+ ACE_Unbounded_Queue<ACE_POSIX_Asynch_Result *> result_queue_;
+};
+
+/**
+ * @class ACE_POSIX_SIG_Proactor
+ *
+ * @brief This Proactor implementation does compeltion querying using
+ * POSIX Real Time signals. <sigtimedwait>/<sigwaitinfo> call is
+ * used to get the notify/get the completions.
+ * The real-time signals that are going to be used with this
+ * Proactor should be given apriori in the constructor, so that
+ * those signals can be masked from asynchornous delivery.
+ */
+class ACE_Export ACE_POSIX_SIG_Proactor : public ACE_POSIX_AIOCB_Proactor
+{
+
+ /**
+ * This class does the registering of Asynch Operations with the
+ * Proactor which is necessary in the SIG strategy, because we need
+ * to store the signal number.
+ */
+ friend class ACE_POSIX_SIG_Asynch_Operation;
+
+public:
+ /**
+ * This constructor masks only the <ACE_SIGRTMIN>
+ * real-time signal. Only this signal should be used to issue
+ * asynchronous operations using this Proctor.
+ */
+ ACE_POSIX_SIG_Proactor (size_t nmaxop = ACE_AIO_DEFAULT_SIZE);
+
+ virtual Proactor_Type get_impl_type (void);
+
+ /**
+ * This constructor should be used to tell the Proactor to mask and
+ * wait for the real-time signals specified in this set. Only these
+ * signals should be used by the asynchronous operations when they
+ * use this Proactor.
+ */
+ ACE_POSIX_SIG_Proactor (const sigset_t mask_set,
+ size_t nmaxop = ACE_AIO_DEFAULT_SIZE);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_SIG_Proactor (void);
+
+ /**
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time);
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (void);
+
+ /// Post a result to the completion port of the Proactor.
+ /// now it is implemented in base ACE_POSIX_AIOCB_Proactor class
+ ///virtual int post_completion (ACE_POSIX_Asynch_Result *result);
+
+ /**
+ * If <signal_number> is -1, check with the Proactor and use one of
+ * the signals that is present in the mask set (i.e. the signals for
+ * which the Proactor will be waiting) of the Proactor. If there are
+ * more than one signal, the higher numbered signal will be chosen.
+ */
+ virtual ACE_Asynch_Result_Impl *create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+protected:
+ /// To setup the handler for a real-time signbal.
+ int setup_signal_handler (int signal_number) const;
+
+ /// To mask all the specified signals in a thread.
+ int mask_signals (const sigset_t *signals) const;
+
+ /**
+ * Dispatch a single set of events. If <milli_seconds> elapses
+ * before any events occur, return 0. Return 1 if a completion is
+ * dispatched. Return -1 on errors.
+ */
+ virtual int handle_events (u_long milli_seconds);
+
+ /**
+ * These signals are used for completion notification by the
+ * Proactor. The signals specified while issueing <Asynch
+ * Operation>s are stored here in this set. These signals are masked
+ * for a thread when it calls the Proactor::handle_events.
+ */
+
+ /// Find free slot to store result and aiocb pointer
+ virtual int allocate_aio_slot (ACE_POSIX_Asynch_Result *result);
+
+
+ /// Notify queue of "post_completed" ACE_POSIX_Asynch_Results
+ /// called from post_completion method
+ virtual int notify_completion ( int sig_num );
+
+ sigset_t RT_completion_signals_;
+};
+
+/**
+ * @class ACE_POSIX_Asynch_Timer
+ *
+ * @brief This class is posted to the completion port when a timer
+ * expires. When the <complete method> of this object is
+ * called, the <handler>'s <handle_timeout> method will be
+ * called.
+ */
+class ACE_Export ACE_POSIX_Asynch_Timer : public ACE_POSIX_Asynch_Result
+{
+
+ /// The factory method for this class is with the POSIX_Proactor
+ /// class.
+ friend class ACE_POSIX_Proactor;
+ friend class ACE_POSIX_SIG_Proactor;
+
+protected:
+ /// Constructor.
+ ACE_POSIX_Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Destructor.
+ virtual ~ACE_POSIX_Asynch_Timer (void) {}
+
+ /// This method calls the <handler>'s handle_timeout method.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0);
+
+ /// Time value requested by caller
+ ACE_Time_Value time_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/POSIX_Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_AIO_CALLS */
+#endif /* ACE_POSIX_PROACTOR_H */
diff --git a/ace/Demux/POSIX_Proactor.i b/ace/Demux/POSIX_Proactor.i
new file mode 100644
index 00000000000..e9935da90c9
--- /dev/null
+++ b/ace/Demux/POSIX_Proactor.i
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+ACE_POSIX_Proactor::Proactor_Type ACE_POSIX_Proactor::get_impl_type (void)
+{
+ return PROACTOR_POSIX;
+}
+
+ACE_INLINE
+ACE_POSIX_Proactor::Proactor_Type ACE_POSIX_AIOCB_Proactor::get_impl_type (void)
+{
+ return PROACTOR_AIOCB;
+}
+
+ACE_INLINE
+ACE_POSIX_Proactor::Proactor_Type ACE_POSIX_SIG_Proactor::get_impl_type (void)
+{
+ return PROACTOR_SIG;
+}
diff --git a/ace/Demux/Priority_Reactor.cpp b/ace/Demux/Priority_Reactor.cpp
new file mode 100644
index 00000000000..fd66ba55e7d
--- /dev/null
+++ b/ace/Demux/Priority_Reactor.cpp
@@ -0,0 +1,171 @@
+// $Id$
+
+#include "ace/Priority_Reactor.h"
+#include "ace/Malloc_T.h"
+
+ACE_RCSID(ace, Priority_Reactor, "$Id$")
+
+typedef ACE_Unbounded_Queue_Iterator<ACE_Event_Tuple> QUEUE_ITERATOR;
+// Its iterator.
+
+typedef ACE_Cached_Allocator<ACE_Node<ACE_Event_Tuple>, ACE_SYNCH_NULL_MUTEX> TUPLE_ALLOCATOR;
+// Defines the memory allocator used, no need for locking because it
+// is only used in one thread of control.
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Priority_Reactor)
+
+// Initialize ACE_Select_Reactor.
+
+#define npriorities \
+ ACE_Event_Handler::HI_PRIORITY-ACE_Event_Handler::LO_PRIORITY+1
+
+void
+ACE_Priority_Reactor::init_bucket (void)
+{
+ // Allocate enough space for all the handles.
+ // TODO: This can be wrong, maybe we should use other kind of
+ // allocator here?
+ ACE_NEW (this->tuple_allocator_,
+ TUPLE_ALLOCATOR (ACE_Select_Reactor::DEFAULT_SIZE));
+
+ // The event handlers are assigned to a new As the Event
+ ACE_NEW (this->bucket_,
+ QUEUE *[npriorities]);
+
+ // This loops "ensures" exception safety.
+ for (int i = 0; i < npriorities; ++i)
+ ACE_NEW (this->bucket_[i],
+ QUEUE (this->tuple_allocator_));
+}
+
+ACE_Priority_Reactor::ACE_Priority_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : ACE_Select_Reactor(sh, tq),
+ bucket_ (0),
+ tuple_allocator_ (0)
+{
+ ACE_TRACE ("ACE_Priority_Reactor::ACE_Priority_Reactor");
+ this->init_bucket ();
+}
+
+ACE_Priority_Reactor::ACE_Priority_Reactor (size_t size,
+ int rs,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : ACE_Select_Reactor (size, rs, sh, tq),
+ bucket_ (0),
+ tuple_allocator_ (0)
+{
+ ACE_TRACE ("ACE_Priority_Reactor::ACE_Priority_Reactor");
+ this->init_bucket ();
+}
+
+ACE_Priority_Reactor::~ACE_Priority_Reactor (void)
+{
+ ACE_TRACE ("ACE_Priority_Reactor::~ACE_Priority_Reactor");
+
+ for (int i = 0; i < npriorities; ++i)
+ delete this->bucket_[i];
+
+ delete[] this->bucket_;
+ delete tuple_allocator_;
+}
+
+int
+ACE_Priority_Reactor::dispatch_io_set (int number_of_active_handles,
+ int& number_dispatched,
+ int mask,
+ ACE_Handle_Set& dispatch_mask,
+ ACE_Handle_Set& ready_mask,
+ ACE_EH_PTMF callback)
+{
+ ACE_TRACE ("ACE_Priority_Reactor::dispatch_io_set");
+
+ if (number_of_active_handles == 0)
+ return 0;
+
+ // The range for which there exists any Event_Tuple is computed on
+ // the ordering loop, minimizing iterations on the dispatching loop.
+ int min_priority = ACE_Event_Handler::HI_PRIORITY;
+ int max_priority = ACE_Event_Handler::LO_PRIORITY;
+
+ ACE_Handle_Set_Iterator handle_iter (dispatch_mask);
+
+ for (ACE_HANDLE handle;
+ (handle = handle_iter ()) != ACE_INVALID_HANDLE;
+ )
+ {
+ ACE_Event_Tuple et (this->handler_rep_.find (handle),
+ handle);
+ int prio = et.event_handler_->priority ();
+
+ // If the priority is out of range assign the minimum priority.
+ if (prio < ACE_Event_Handler::LO_PRIORITY
+ || prio > ACE_Event_Handler::HI_PRIORITY)
+ prio = ACE_Event_Handler::LO_PRIORITY;
+
+ bucket_[prio]->enqueue_tail (et);
+
+ // Update the priority ranges....
+ if (min_priority > prio)
+ min_priority = prio;
+ if (max_priority < prio)
+ max_priority = prio;
+ }
+
+ for (int i = max_priority; i >= min_priority; --i)
+ {
+ // Remove all the entries from the wrappers
+ while (!bucket_[i]->is_empty ()
+ && number_dispatched < number_of_active_handles
+ && this->state_changed_ == 0)
+ {
+ ACE_Event_Tuple et;
+ bucket_[i]->dequeue_head (et);
+ this->notify_handle (et.handle_,
+ mask,
+ ready_mask,
+ et.event_handler_,
+ callback);
+ number_dispatched++;
+ }
+ // Even if we are aborting the loop due to this->state_changed
+ // or another error we still want to cleanup the buckets.
+ bucket_[i]->reset ();
+ }
+
+ if (number_dispatched > 0 && this->state_changed_)
+ return -1;
+
+ return 0;
+}
+
+void
+ACE_Priority_Reactor::dump (void) const
+{
+ ACE_TRACE ("ACE_Priority_Reactor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_Select_Reactor::dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Unbounded_Queue<ACE_Event_Tuple>;
+template class ACE_Unbounded_Queue_Iterator<ACE_Event_Tuple>;
+template class ACE_Node<ACE_Event_Tuple>;
+template class ACE_Cached_Allocator<ACE_Node<ACE_Event_Tuple>, ACE_SYNCH_NULL_MUTEX>;
+template class ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> >,ACE_SYNCH_NULL_MUTEX>;
+template class ACE_Free_List<ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> > >;
+template class ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> >;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Unbounded_Queue<ACE_Event_Tuple>
+#pragma instantiate ACE_Unbounded_Queue_Iterator<ACE_Event_Tuple>
+#pragma instantiate ACE_Node<ACE_Event_Tuple>
+#pragma instantiate ACE_Cached_Allocator<ACE_Node<ACE_Event_Tuple>, ACE_SYNCH_NULL_MUTEX>
+#pragma instantiate ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> >,ACE_SYNCH_NULL_MUTEX>
+#pragma instantiate ACE_Free_List<ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> > >
+#pragma instantiate ACE_Cached_Mem_Pool_Node<ACE_Node<ACE_Event_Tuple> >
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Demux/Priority_Reactor.h b/ace/Demux/Priority_Reactor.h
new file mode 100644
index 00000000000..23fa0e3ae24
--- /dev/null
+++ b/ace/Demux/Priority_Reactor.h
@@ -0,0 +1,89 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Priority_Reactor.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PRIORITY_REACTOR_H
+#define ACE_PRIORITY_REACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Unbounded_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Select_Reactor.h"
+
+/**
+ * @class ACE_Priority_Reactor
+ *
+ * @brief Implements priority based dispatching.
+ *
+ * This class refines the dispatching mechanism for the
+ * Select_Reactor by taking advantage of the priority method on
+ * ACE_Event_Handler.
+ */
+class ACE_Export ACE_Priority_Reactor : public ACE_Select_Reactor
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Initialize <ACE_Priority_Reactor> with the default size.
+ ACE_Priority_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /// Initialize <ACE_Priority_Reactor> with size <size>.
+ ACE_Priority_Reactor (size_t size,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /// Close down the select_reactor and release all of its resources.
+ virtual ~ACE_Priority_Reactor (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Dispatching methods.
+
+ /// We simply override this function to implement the priority
+ /// dispatching.
+ virtual int dispatch_io_set (int number_of_active_handles,
+ int &number_dispatched,
+ int mask,
+ ACE_Handle_Set &dispatch_mask,
+ ACE_Handle_Set &ready_mask,
+ ACE_EH_PTMF callback);
+
+private:
+ /// A small helper to initialize the bucket.
+ void init_bucket (void);
+
+ /// There is a queue per-priority, which simply holds the
+ /// Event_Handlers until we know who goes first.
+ typedef ACE_Unbounded_Queue<ACE_Event_Tuple> QUEUE;
+ QUEUE** bucket_;
+
+ /// The queues themselves use this allocator to minimize dynamic
+ /// memory usage.
+ ACE_Allocator* tuple_allocator_;
+
+ /// Deny access since member-wise won't work...
+ ACE_Priority_Reactor (const ACE_Select_Reactor &);
+ ACE_Priority_Reactor &operator = (const ACE_Select_Reactor &);
+};
+
+#include "ace/post.h"
+#endif /* ACE_PRIORITY_REACTOR_H */
diff --git a/ace/Demux/Proactor.cpp b/ace/Demux/Proactor.cpp
new file mode 100644
index 00000000000..8fe6c8c982c
--- /dev/null
+++ b/ace/Demux/Proactor.cpp
@@ -0,0 +1,1110 @@
+// $Id$
+
+#include "ace/Proactor.h"
+#include "ace/Proactor_Impl.h"
+#include "ace/Object_Manager.h"
+#include "ace/Task_T.h"
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_ACE_SVCCONF)
+# include "ace/Service_Config.h"
+# endif /* !ACE_HAS_WINCE && !ACE_LACKS_ACE_SVCCONF */
+
+ACE_RCSID(ace, Proactor, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+// This only works on Win32 platforms and on Unix platforms with aio
+// calls.
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_HAS_AIO_CALLS)
+# include "ace/POSIX_Proactor.h"
+#else /* !ACE_HAS_AIO_CALLS */
+# include "ace/WIN32_Proactor.h"
+#endif /* ACE_HAS_AIO_CALLS */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+// Process-wide ACE_Proactor.
+ACE_Proactor *ACE_Proactor::proactor_ = 0;
+
+// Controls whether the Proactor is deleted when we shut down (we can
+// only delete it safely if we created it!)
+int ACE_Proactor::delete_proactor_ = 0;
+
+class ACE_Export ACE_Proactor_Timer_Handler : public ACE_Task <ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // A Handler for timer. It helps in the management of timers
+ // registered with the Proactor.
+ //
+ // = DESCRIPTION
+ // This object has a thread that will wait on the earliest time
+ // in a list of timers and an event. When a timer expires, the
+ // thread will post a completion event on the port and go back
+ // to waiting on the timer queue and event. If the event is
+ // signaled, the thread will refresh the time it is currently
+ // waiting on (in case the earliest time has changed).
+
+ friend class ACE_Proactor;
+ // Proactor has special privileges
+ // Access needed to: timer_event_
+
+public:
+ ACE_Proactor_Timer_Handler (ACE_Proactor &proactor);
+ // Constructor.
+
+ virtual ~ACE_Proactor_Timer_Handler (void);
+ // Destructor.
+
+ int destroy (void);
+ // Proactor calls this to shut down the timer handler
+ // gracefully. Just calling the destructor alone doesnt do what
+ // <destroy> does. <destroy> make sure the thread exits properly.
+
+protected:
+ virtual int svc (void);
+ // Run by a daemon thread to handle deferred processing. In other
+ // words, this method will do the waiting on the earliest timer and
+ // event.
+
+ ACE_Auto_Event timer_event_;
+ // Event to wait on.
+
+ ACE_Proactor &proactor_;
+ // Proactor.
+
+ int shutting_down_;
+ // Flag used to indicate when we are shutting down.
+};
+
+ACE_Proactor_Timer_Handler::ACE_Proactor_Timer_Handler (ACE_Proactor &proactor)
+ : ACE_Task <ACE_NULL_SYNCH> (&proactor.thr_mgr_),
+ proactor_ (proactor),
+ shutting_down_ (0)
+{
+}
+
+ACE_Proactor_Timer_Handler::~ACE_Proactor_Timer_Handler (void)
+{
+ // Mark for closing down.
+ this->shutting_down_ = 1;
+
+ // Signal timer event.
+ this->timer_event_.signal ();
+
+ // Wait for the Timer Handler thread to exit.
+ this->thr_mgr ()->wait_grp (this->grp_id ());
+}
+
+int
+ACE_Proactor_Timer_Handler::svc (void)
+{
+ ACE_Time_Value absolute_time;
+ ACE_Time_Value relative_time;
+ int result = 0;
+
+ while (this->shutting_down_ == 0)
+ {
+ // Check whether the timer queue has any items in it.
+ if (this->proactor_.timer_queue ()->is_empty () == 0)
+ {
+ // Get the earliest absolute time.
+ absolute_time = this->proactor_.timer_queue ()->earliest_time ();
+
+ // Get current time from timer queue since we don't know
+ // which <gettimeofday> was used.
+ ACE_Time_Value cur_time = this->proactor_.timer_queue ()->gettimeofday ();
+
+ // Compare absolute time with curent time received from the
+ // timer queue.
+ if (absolute_time > cur_time)
+ relative_time = absolute_time - cur_time;
+ else
+ relative_time = 0;
+
+ // Block for relative time.
+ result = this->timer_event_.wait (&relative_time, 0);
+ }
+ else
+ // The timer queue has no entries, so wait indefinitely.
+ result = this->timer_event_.wait ();
+
+ // Check for timer expiries.
+ if (result == -1)
+ {
+ switch (errno)
+ {
+ case ETIME:
+ // timeout: expire timers
+ this->proactor_.timer_queue ()->expire ();
+ break;
+ default:
+ // Error.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_LIB_TEXT ("ACE_Proactor_Timer_Handler::svc:wait failed")),
+ -1);
+ }
+ }
+ }
+ return 0;
+}
+
+// *********************************************************************
+
+ACE_Proactor_Handle_Timeout_Upcall::ACE_Proactor_Handle_Timeout_Upcall (void)
+ : proactor_ (0)
+{
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *act,
+ const ACE_Time_Value &time)
+{
+ ACE_UNUSED_ARG (timer_queue);
+
+ if (this->proactor_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%t) No Proactor set in ACE_Proactor_Handle_Timeout_Upcall,")
+ ACE_LIB_TEXT (" no completion port to post timeout to?!@\n")),
+ -1);
+
+ // Create the Asynch_Timer.
+ ACE_Asynch_Result_Impl *asynch_timer = this->proactor_->create_asynch_timer (*handler,
+ act,
+ time,
+ ACE_INVALID_HANDLE,
+ 0,
+ -1);
+ if (asynch_timer == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_LIB_TEXT ("ACE_Proactor_Handle_Timeout_Upcall::timeout:")
+ ACE_LIB_TEXT ("create_asynch_timer failed")),
+ -1);
+
+ // Post a completion.
+ if (asynch_timer->post_completion (this->proactor_->implementation ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Failure in dealing with timers: ")
+ ACE_LIB_TEXT ("PostQueuedCompletionStatus failed\n")),
+ -1);
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler)
+{
+ ACE_UNUSED_ARG (timer_queue);
+ ACE_UNUSED_ARG (handler);
+
+ // Do nothing
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::deletion (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg)
+{
+ ACE_UNUSED_ARG (timer_queue);
+ ACE_UNUSED_ARG (handler);
+ ACE_UNUSED_ARG (arg);
+
+ // Do nothing
+ return 0;
+}
+
+int
+ACE_Proactor_Handle_Timeout_Upcall::proactor (ACE_Proactor &proactor)
+{
+ if (this->proactor_ == 0)
+ {
+ this->proactor_ = &proactor;
+ return 0;
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_Proactor_Handle_Timeout_Upcall is only suppose")
+ ACE_LIB_TEXT (" to be used with ONE (and only one) Proactor\n")),
+ -1);
+}
+
+// *********************************************************************
+
+ACE_Proactor::ACE_Proactor (ACE_Proactor_Impl *implementation,
+ int delete_implementation,
+ TIMER_QUEUE *tq)
+ : implementation_ (0),
+ delete_implementation_ (delete_implementation),
+ timer_handler_ (0),
+ timer_queue_ (0),
+ delete_timer_queue_ (0),
+ end_event_loop_ (0),
+ event_loop_thread_count_ (0)
+{
+ this->implementation (implementation);
+
+ if (this->implementation () == 0)
+ {
+#if defined (ACE_HAS_AIO_CALLS)
+ // POSIX Proactor.
+ #if defined (ACE_POSIX_AIOCB_PROACTOR)
+ ACE_NEW (implementation,
+ ACE_POSIX_AIOCB_Proactor);
+ #elif defined (ACE_POSIX_SIG_PROACTOR)
+ ACE_NEW (implementation,
+ ACE_POSIX_SIG_Proactor);
+ #else /* Default is to use the SIG one */
+ ACE_NEW (implementation,
+ ACE_POSIX_SIG_Proactor);
+ #endif
+#elif (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+ // WIN_Proactor.
+ ACE_NEW (implementation,
+ ACE_WIN32_Proactor);
+#endif /* ACE_HAS_AIO_CALLS */
+ this->implementation (implementation);
+ this->delete_implementation_ = 1;
+ }
+
+ // Set the timer queue.
+ this->timer_queue (tq);
+
+ // Create the timer handler
+ ACE_NEW (this->timer_handler_,
+ ACE_Proactor_Timer_Handler (*this));
+
+ // Activate <timer_handler>.
+ if (this->timer_handler_->activate (THR_NEW_LWP) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_LIB_TEXT ("Task::activate:could not create thread\n")));
+}
+
+ACE_Proactor::~ACE_Proactor (void)
+{
+ this->close ();
+}
+
+ACE_Proactor *
+ACE_Proactor::instance (size_t /* threads */)
+{
+ ACE_TRACE ("ACE_Proactor::instance");
+
+ if (ACE_Proactor::proactor_ == 0)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (),
+ 0));
+
+ if (ACE_Proactor::proactor_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_Proactor::proactor_,
+ ACE_Proactor,
+ 0);
+
+ ACE_Proactor::delete_proactor_ = 1;
+ }
+ }
+ return ACE_Proactor::proactor_;
+}
+
+ACE_Proactor *
+ACE_Proactor::instance (ACE_Proactor * r, int delete_proactor)
+{
+ ACE_TRACE ("ACE_Proactor::instance");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ ACE_Proactor *t = ACE_Proactor::proactor_;
+
+ ACE_Proactor::delete_proactor_ = delete_proactor;
+ ACE_Proactor::proactor_ = r;
+
+ return t;
+}
+
+void
+ACE_Proactor::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Proactor::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Proactor::delete_proactor_)
+ {
+
+ delete ACE_Proactor::proactor_;
+ ACE_Proactor::proactor_ = 0;
+ ACE_Proactor::delete_proactor_ = 0;
+ }
+}
+
+int
+ACE_Proactor::check_reconfiguration (ACE_Proactor *)
+{
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_ACE_SVCCONF)
+ if (ACE_Service_Config::reconfig_occurred ())
+ {
+ ACE_Service_Config::reconfigure ();
+ return 1;
+ }
+#endif /* ! ACE_HAS_WINCE || ! ACE_LACKS_ACE_SVCCONF */
+ return 0;
+}
+
+int
+ACE_Proactor::proactor_run_event_loop (PROACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Proactor::proactor_run_event_loop");
+ int result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ // Early check. It is ok to do this without lock, since we care just
+ // whether it is zero or non-zero.
+ if (this->end_event_loop_ != 0)
+ return 0;
+
+ // First time you are in. Increment the thread count.
+ this->event_loop_thread_count_ ++;
+ }
+
+ // Run the event loop.
+ for (;;)
+ {
+ // Check the end loop flag. It is ok to do this without lock,
+ // since we care just whether it is zero or non-zero.
+ if (this->end_event_loop_ != 0)
+ break;
+
+ // <end_event_loop> is not set. Ready to do <handle_events>.
+ result = this->handle_events ();
+
+ if (eh != 0 && (*eh) (this))
+ continue;
+
+ if (result == -1)
+ break;
+ }
+
+ // Leaving the event loop. Decrement the thread count.
+
+ {
+ // Obtain the lock in the MT environments.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ // Decrement the thread count.
+ this->event_loop_thread_count_ --;
+
+ if (this->event_loop_thread_count_ > 0
+ && this->end_event_loop_ != 0)
+ this->proactor_post_wakeup_completions (1);
+ }
+
+ return result;
+}
+
+// Handle events for -tv- time. handle_events updates -tv- to reflect
+// time elapsed, so do not return until -tv- == 0, or an error occurs.
+int
+ACE_Proactor::proactor_run_event_loop (ACE_Time_Value &tv,
+ PROACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Proactor::proactor_run_event_loop");
+ int result = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ // Early check. It is ok to do this without lock, since we care just
+ // whether it is zero or non-zero.
+ if (this->end_event_loop_ != 0
+ || tv == ACE_Time_Value::zero)
+ return 0;
+
+ // First time you are in. Increment the thread count.
+ this->event_loop_thread_count_ ++;
+ }
+
+ // Run the event loop.
+ for (;;)
+ {
+ // Check the end loop flag. It is ok to do this without lock,
+ // since we care just whether it is zero or non-zero.
+ if (this->end_event_loop_ != 0)
+ break;
+
+ // <end_event_loop> is not set. Ready to do <handle_events>.
+ result = this->handle_events (tv);
+
+ if (eh != 0 && (*eh) (this))
+ continue;
+
+ if (result == -1)
+ break;
+ }
+
+ // Leaving the event loop. Decrement the thread count.
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ // Decrement the thread count.
+ this->event_loop_thread_count_ --;
+
+ if (this->event_loop_thread_count_ > 0
+ && this->end_event_loop_ != 0)
+ this->proactor_post_wakeup_completions (1);
+ }
+
+ return result;
+}
+
+int
+ACE_Proactor::proactor_reset_event_loop(void)
+{
+ ACE_TRACE ("ACE_Proactor::proactor_reset_event_loop");
+
+ // Obtain the lock in the MT environments.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ this->end_event_loop_ = 0;
+ return 0;
+}
+
+int
+ACE_Proactor::proactor_end_event_loop (void)
+{
+ ACE_TRACE ("ACE_Proactor::proactor_end_event_loop");
+
+ int how_many = 0;
+
+ {
+ // Obtain the lock, set the end flag and post the wakeup
+ // completions.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ // Set the end flag.
+ ACE_Proactor::end_event_loop_ = 1;
+
+ // Number of completions to post.
+ how_many = ACE_Proactor::event_loop_thread_count_;
+
+ if (how_many == 0)
+ return 0;
+ }
+
+ // Post completions to all the threads so that they will all wake
+ // up.
+ return this->proactor_post_wakeup_completions (how_many);
+}
+
+int
+ACE_Proactor::proactor_event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Proactor::proactor_event_loop_done");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ return this->end_event_loop_ != 0 ? 1 : 0 ;
+}
+
+int
+ACE_Proactor::close (void)
+{
+ // Close the implementation.
+ if (this->implementation ()->close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%N:%l:(%P | %t):%p\n"),
+ ACE_LIB_TEXT ("ACE_Proactor::close:implementation couldnt be closed")),
+ -1);
+
+ // Delete the implementation.
+ if (this->delete_implementation_)
+ {
+ delete this->implementation ();
+ this->implementation_ = 0;
+ }
+
+ // Delete the timer handler.
+ if (this->timer_handler_)
+ {
+ delete this->timer_handler_;
+ this->timer_handler_ = 0;
+ }
+
+ // Delete the timer queue.
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = 0;
+ }
+
+ return 0;
+}
+
+int
+ACE_Proactor::register_handle (ACE_HANDLE handle,
+ const void *completion_key)
+{
+ return this->implementation ()->register_handle (handle,
+ completion_key);
+}
+
+long
+ACE_Proactor::schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time)
+{
+ return this->schedule_timer (handler,
+ act,
+ time,
+ ACE_Time_Value::zero);
+}
+
+long
+ACE_Proactor::schedule_repeating_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &interval)
+{
+ return this->schedule_timer (handler,
+ act,
+ interval,
+ interval);
+}
+
+long
+ACE_Proactor::schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time,
+ const ACE_Time_Value &interval)
+{
+ // absolute time.
+ ACE_Time_Value absolute_time =
+ this->timer_queue_->gettimeofday () + time;
+
+ // Only one guy goes in here at a time
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
+ ace_mon,
+ this->timer_queue_->mutex (),
+ -1));
+
+ // Schedule the timer
+ long result = this->timer_queue_->schedule (&handler,
+ act,
+ absolute_time,
+ interval);
+ if (result != -1)
+ {
+ // no failures: check to see if we are the earliest time
+ if (this->timer_queue_->earliest_time () == absolute_time)
+
+ // wake up the timer thread
+ if (this->timer_handler_->timer_event_.signal () == -1)
+ {
+ // Cancel timer
+ this->timer_queue_->cancel (result);
+ result = -1;
+ }
+ }
+ return result;
+}
+
+int
+ACE_Proactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ // No need to singal timer event here. Even if the cancel timer was
+ // the earliest, we will have an extra wakeup.
+ return this->timer_queue_->cancel (timer_id,
+ arg,
+ dont_call_handle_close);
+}
+
+int
+ACE_Proactor::cancel_timer (ACE_Handler &handler,
+ int dont_call_handle_close)
+{
+ // No need to signal timer event here. Even if the cancel timer was
+ // the earliest, we will have an extra wakeup.
+ return this->timer_queue_->cancel (&handler,
+ dont_call_handle_close);
+}
+
+int
+ACE_Proactor::handle_events (ACE_Time_Value &wait_time)
+{
+ return implementation ()->handle_events (wait_time);
+}
+
+int
+ACE_Proactor::handle_events (void)
+{
+ return this->implementation ()->handle_events ();
+}
+
+int
+ACE_Proactor::wake_up_dispatch_threads (void)
+{
+ return 0;
+}
+
+int
+ACE_Proactor::close_dispatch_threads (int)
+{
+ return 0;
+}
+
+size_t
+ACE_Proactor::number_of_threads (void) const
+{
+ return this->implementation ()->number_of_threads ();
+}
+
+void
+ACE_Proactor::number_of_threads (size_t threads)
+{
+ this->implementation ()->number_of_threads (threads);
+}
+
+ACE_Proactor::TIMER_QUEUE *
+ACE_Proactor::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+void
+ACE_Proactor::timer_queue (TIMER_QUEUE *tq)
+{
+ // Cleanup old timer queue.
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->delete_timer_queue_ = 0;
+ }
+
+ // New timer queue.
+ if (tq == 0)
+ {
+ ACE_NEW (this->timer_queue_,
+ TIMER_HEAP);
+ this->delete_timer_queue_ = 1;
+ }
+ else
+ {
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = 0;
+ }
+
+ // Set the proactor in the timer queue's functor
+ this->timer_queue_->upcall_functor ().proactor (*this);
+}
+
+ACE_HANDLE
+ACE_Proactor::get_handle (void) const
+{
+ return this->implementation ()->get_handle ();
+}
+
+ACE_Proactor_Impl *
+ACE_Proactor::implementation (void) const
+{
+ return this->implementation_;
+}
+
+
+ACE_Asynch_Read_Stream_Impl *
+ACE_Proactor::create_asynch_read_stream (void)
+{
+ return this->implementation ()->create_asynch_read_stream ();
+}
+
+ACE_Asynch_Write_Stream_Impl *
+ACE_Proactor::create_asynch_write_stream (void)
+{
+ return this->implementation ()->create_asynch_write_stream ();
+}
+
+ACE_Asynch_Read_Dgram_Impl *
+ACE_Proactor::create_asynch_read_dgram (void)
+{
+ return this->implementation ()->create_asynch_read_dgram ();
+}
+
+ACE_Asynch_Write_Dgram_Impl *
+ACE_Proactor::create_asynch_write_dgram (void)
+{
+ return this->implementation ()->create_asynch_write_dgram ();
+}
+
+ACE_Asynch_Read_File_Impl *
+ACE_Proactor::create_asynch_read_file (void)
+{
+ return this->implementation ()->create_asynch_read_file ();
+}
+
+ACE_Asynch_Write_File_Impl *
+ACE_Proactor::create_asynch_write_file (void)
+{
+ return this->implementation ()->create_asynch_write_file ();
+}
+
+ACE_Asynch_Accept_Impl *
+ACE_Proactor::create_asynch_accept (void)
+{
+ return this->implementation ()->create_asynch_accept ();
+}
+
+ACE_Asynch_Transmit_File_Impl *
+ACE_Proactor::create_asynch_transmit_file (void)
+{
+ return this->implementation ()->create_asynch_transmit_file ();
+}
+
+ACE_Asynch_Read_Stream_Result_Impl *
+ACE_Proactor::create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->create_asynch_read_stream_result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+
+ACE_Asynch_Write_Stream_Result_Impl *
+ACE_Proactor::create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+{
+ return this->implementation ()->create_asynch_write_stream_result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Read_File_Result_Impl *
+ACE_Proactor::create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+{
+ return this->implementation ()->create_asynch_read_file_result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Write_File_Result_Impl *
+ACE_Proactor::create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+{
+ return this->implementation ()->create_asynch_write_file_result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl *
+ACE_Proactor::create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation()->create_asynch_read_dgram_result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ flags,
+ protocol_family,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl *
+ACE_Proactor::create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation()->create_asynch_write_dgram_result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Accept_Result_Impl *
+ACE_Proactor::create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+{
+ return this->implementation ()->create_asynch_accept_result (handler,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_Proactor::create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+
+{
+ return this->implementation ()->create_asynch_transmit_file_result (handler,
+ socket,
+ file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number);
+}
+
+ACE_Asynch_Result_Impl *
+ACE_Proactor::create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ return this->implementation ()->create_asynch_timer (handler,
+ act,
+ tv,
+ event,
+ priority,
+ signal_number);
+}
+
+int
+ACE_Proactor::proactor_post_wakeup_completions (int how_many)
+{
+ return this->implementation ()->post_wakeup_completions (how_many);
+}
+
+void
+ACE_Proactor::implementation (ACE_Proactor_Impl *implementation)
+{
+ this->implementation_ = implementation;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Timer_Queue_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Queue_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_List_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_List_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Node_T<ACE_Handler *>;
+template class ACE_Unbounded_Set<ACE_Timer_Node_T<ACE_Handler *> *>;
+template class ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<ACE_Handler *> *>;
+template class ACE_Node <ACE_Timer_Node_T<ACE_Handler *> *>;
+template class ACE_Free_List<ACE_Timer_Node_T<ACE_Handler *> >;
+template class ACE_Locked_Free_List<ACE_Timer_Node_T<ACE_Handler *>, ACE_Null_Mutex>;
+template class ACE_Timer_Heap_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Heap_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Wheel_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Wheel_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Timer_Queue_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_Queue_Iterator_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_List_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_List_Iterator_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_Node_T<ACE_Handler *>
+#pragma instantiate ACE_Unbounded_Set<ACE_Timer_Node_T<ACE_Handler *> *>
+#pragma instantiate ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<ACE_Handler *> *>
+#pragma instantiate ACE_Node <ACE_Timer_Node_T<ACE_Handler *> *>
+#pragma instantiate ACE_Free_List<ACE_Timer_Node_T<ACE_Handler *> >
+#pragma instantiate ACE_Locked_Free_List<ACE_Timer_Node_T<ACE_Handler *>,\
+ ACE_Null_Mutex>
+#pragma instantiate ACE_Timer_Heap_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_Heap_Iterator_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_Wheel_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#pragma instantiate ACE_Timer_Wheel_Iterator_T<ACE_Handler *,\
+ ACE_Proactor_Handle_Timeout_Upcall,\
+ ACE_SYNCH_RECURSIVE_MUTEX>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+#else /* !ACE_WIN32 || !ACE_HAS_AIO_CALLS */
+
+ACE_Proactor *
+ACE_Proactor::instance (size_t threads)
+{
+ ACE_UNUSED_ARG (threads);
+ return 0;
+}
+
+ACE_Proactor *
+ACE_Proactor::instance (ACE_Proactor *)
+{
+ return 0;
+}
+
+void
+ACE_Proactor::close_singleton (void)
+{
+}
+
+int
+ACE_Proactor::run_event_loop (void)
+{
+ // not implemented
+ return -1;
+}
+
+int
+ACE_Proactor::run_event_loop (ACE_Time_Value &tv)
+{
+ // not implemented
+ ACE_UNUSED_ARG (tv);
+ return -1;
+}
+
+int
+ACE_Proactor::end_event_loop (void)
+{
+ // not implemented
+ return -1;
+}
+
+sig_atomic_t
+ACE_Proactor::event_loop_done (void)
+{
+ return sig_atomic_t (1);
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS*/
diff --git a/ace/Demux/Proactor.h b/ace/Demux/Proactor.h
new file mode 100644
index 00000000000..6209a8ad420
--- /dev/null
+++ b/ace/Demux/Proactor.h
@@ -0,0 +1,601 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Proactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Alexander Libman <alibman@@ihug.com.au>
+ */
+//=============================================================================
+
+#ifndef ACE_PROACTOR_H
+#define ACE_PROACTOR_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+// This only works on Win32 platforms and on Unix platforms supporting
+// POSIX aio calls.
+
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Timer_Queue.h"
+#include "ace/Timer_List.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_Wheel.h"
+
+// Forward declarations.
+class ACE_Proactor_Impl;
+class ACE_Proactor_Timer_Handler;
+
+/**
+ * @class ACE_Proactor_Handle_Timeout_Upcall
+ *
+ * @brief Functor for <ACE_Timer_Queue>.
+ *
+ * This class implements the functor required by the Timer
+ * Queue to call <handle_timeout> on ACE_Handlers.
+ */
+class ACE_Export ACE_Proactor_Handle_Timeout_Upcall
+{
+
+ /// Type def for the timer queue.
+ typedef ACE_Timer_Queue_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_QUEUE;
+
+ /// The main Proactor class has special permissions.
+ friend class ACE_Proactor;
+
+public:
+ /// Constructor.
+ ACE_Proactor_Handle_Timeout_Upcall (void);
+
+ /// This method is called when the timer expires.
+ int timeout (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time);
+
+ /// This method is called when the timer is canceled.
+ int cancellation (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler);
+
+ /// This method is called when the timer queue is destroyed and the
+ /// timer is still contained in it.
+ int deletion (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg);
+
+protected:
+ /// Set the proactor. This will fail, if one is already set!
+ int proactor (ACE_Proactor &proactor);
+
+ /// Handle to the proactor. This is needed for posting a timer result
+ /// to the Proactor's completion queue.
+ ACE_Proactor *proactor_;
+};
+
+/**
+ * @class ACE_Proactor
+ *
+ * @brief A manager for asynchronous event demultiplexing.
+ *
+ * See the Proactor pattern description at
+ * http://www.cs.wustl.edu/~schmidt/proactor.ps.gz for more
+ * details.
+ */
+class ACE_Export ACE_Proactor
+{
+ // = Here are the private typedefs that the <ACE_Proactor> uses.
+
+ typedef ACE_Timer_Queue_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_QUEUE_ITERATOR;
+ typedef ACE_Timer_List_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_LIST;
+ typedef ACE_Timer_List_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_LIST_ITERATOR;
+ typedef ACE_Timer_Heap_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_HEAP;
+ typedef ACE_Timer_Heap_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_HEAP_ITERATOR;
+ typedef ACE_Timer_Wheel_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_WHEEL;
+ typedef ACE_Timer_Wheel_Iterator_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_WHEEL_ITERATOR;
+
+ // = Friendship.
+
+ /// Timer handler runs a thread and manages the timers, on behalf of
+ /// the Proactor.
+ friend class ACE_Proactor_Timer_Handler;
+
+public:
+ /// Public type.
+ typedef ACE_Timer_Queue_T<ACE_Handler *,
+ ACE_Proactor_Handle_Timeout_Upcall,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ TIMER_QUEUE;
+
+ /**
+ * Constructor. If <implementation> is 0, the correct implementation
+ * object will be created. <delete_implementation> flag determines
+ * whether the implementation object should be deleted by the
+ * Proactor or not. If <tq> is 0, a new TIMER_QUEUE is created.
+ */
+ ACE_Proactor (ACE_Proactor_Impl *implementation = 0,
+ int delete_implementation = 0,
+ TIMER_QUEUE *tq = 0);
+
+ /// Virtual destruction.
+ virtual ~ACE_Proactor (void);
+
+ /// Get pointer to a process-wide <ACE_Proactor>. <threads> should
+ /// be part of another method.
+ static ACE_Proactor *instance (size_t threads = 0);
+
+ /// Set pointer to a process-wide <ACE_Proactor> and return existing
+ /// pointer.
+ static ACE_Proactor *instance (ACE_Proactor * proactor,
+ int delete_proactor = 0);
+
+ /// Delete the dynamically allocated Singleton.
+ static void close_singleton (void);
+
+ /// Cleanup method, used by the <ACE_Object_Manager> to destroy the
+ /// singleton.
+ static void cleanup (void *instance, void *arg);
+
+ // = Proactor event loop management methods.
+
+ /// Run the event loop until the <ACE_Proactor::handle_events> method
+ /// returns -1 or the <end_event_loop> method is invoked.
+ static int run_event_loop (void);
+
+ /**
+ * Run the event loop until the <ACE_Proactor::handle_events> method
+ * returns -1, the <end_event_loop> method is invoked, or the
+ * <ACE_Time_Value> expires.
+ */
+ static int run_event_loop (ACE_Time_Value &tv);
+
+ /**
+ * Instruct the <ACE_Proactor::instance> to terminate its event
+ * loop.
+ * This method wakes up all the threads blocked on waiting for
+ * completions and end the event loop.
+ */
+ static int end_event_loop (void);
+
+ /**
+ * Resets the <ACE_Proactor::end_event_loop_> static so that the
+ * <run_event_loop> method can be restarted.
+ */
+ static int reset_event_loop (void);
+
+ /**
+ * The singleton proactor is used by the <ACE_Service_Config>.
+ * Therefore, we must check for the reconfiguration request and
+ * handle it after handling an event.
+ */
+ static int check_reconfiguration (ACE_Proactor *);
+
+ /// Report if the <ACE_Proactor::instance> event loop is finished.
+ static int event_loop_done (void);
+
+ /// Close the IO completion port.
+ virtual int close (void);
+
+ /**
+ * You can add a hook to various run_event methods and the hook will
+ * be called after handling every proactor event. If this function
+ * returns 0, proactor_run_event_loop will check for the return value of
+ * handle_events. If it is -1, the the proactor_run_event_loop will return
+ * (pre-maturely.)
+ */
+ typedef int (*PROACTOR_EVENT_HOOK)(ACE_Proactor *);
+
+ // These methods work with an instance of a proactor.
+ /**
+ * Run the event loop until the
+ * <ACE_Proactor::handle_events>
+ * method returns -1 or the <end_proactor_event_loop> method is invoked.
+ */
+ virtual int proactor_run_event_loop (PROACTOR_EVENT_HOOK = 0);
+
+ /**
+ * Run the event loop until the <ACE_Proactor::handle_events>
+ * method returns -1, the
+ * <end_proactor_event_loop> method is invoked,
+ * or the <ACE_Time_Value>
+ * expires.
+ */
+ virtual int proactor_run_event_loop (ACE_Time_Value &tv,
+ PROACTOR_EVENT_HOOK = 0);
+
+ /**
+ * Instruct the ACE_Proactor to terminate its event loop
+ * and notifies the ACE_Proactor so that it can wake up
+ * and close down gracefully.
+ */
+ virtual int proactor_end_event_loop (void);
+
+ /// Report if the ACE_Proactor event loop is finished.
+ virtual int proactor_event_loop_done (void);
+
+ /// Resets the <ACE_Reactor::end_event_loop_> static so that the
+ /// <run_event_loop> method can be restarted.
+ virtual int proactor_reset_event_loop (void);
+
+
+ /// This method adds the <handle> to the I/O completion port. This
+ /// function is a no-op function for Unix systems and returns 0;
+ virtual int register_handle (ACE_HANDLE handle,
+ const void *completion_key);
+
+ // = Timer management.
+ /**
+ * Schedule a <handler> that will expire after <time>. If it
+ * expires then <act> is passed in as the value to the <handler>'s
+ * <handle_timeout> callback method. This method returns a
+ * <timer_id>. This <timer_id> can be used to cancel a timer before
+ * it expires. The cancellation ensures that <timer_ids> are unique
+ * up to values of greater than 2 billion timers. As long as timers
+ * don't stay around longer than this there should be no problems
+ * with accidentally deleting the wrong timer. Returns -1 on
+ * failure (which is guaranteed never to be a valid <timer_id>).
+ */
+ virtual long schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time);
+
+ virtual long schedule_repeating_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &interval);
+
+ // Same as above except <interval> it is used to reschedule the
+ // <handler> automatically.
+
+ /// This combines the above two methods into one. Mostly for backward
+ /// compatibility.
+ virtual long schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time,
+ const ACE_Time_Value &interval);
+
+ /// Cancel all timers associated with this <handler>. Returns number
+ /// of timers cancelled.
+ virtual int cancel_timer (ACE_Handler &handler,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single <ACE_Handler> that matches the <timer_id> value
+ * (which was returned from the <schedule> method). If <act> is
+ * non-NULL then it will be set to point to the ``magic cookie''
+ * argument passed in when the <Handler> was registered. This makes
+ * it possible to free up the memory and avoid memory leaks.
+ * Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ * wasn't found.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **act = 0,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Dispatch a single set of events, waiting up to a specified time limit
+ * if necessary.
+ * @param wait_time the time to wait for an event to occur. This is
+ * a relative time. On successful return, the time is updated to
+ * reflect the amount of time spent waiting for event(s) to occur.
+ * @return Returns 0 if no events occur before the wait_time expires.
+ * Returns 1 when a completion is dispatched. On error, returns -1
+ * and sets errno accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time);
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * @return Returns 1 when a completion is dispatched. On error, returns -1
+ * and sets errno accordingly.
+ */
+ virtual int handle_events (void);
+
+ /// Add wakeup dispatch threads (reinit).
+ int wake_up_dispatch_threads (void);
+
+ /// Close all dispatch threads.
+ int close_dispatch_threads (int wait);
+
+ /// Number of thread used as a parameter to CreatIoCompletionPort.
+ size_t number_of_threads (void) const;
+ void number_of_threads (size_t threads);
+
+ /// Get/Set timer queue.
+ TIMER_QUEUE *timer_queue (void) const;
+ void timer_queue (TIMER_QUEUE *timer_queue);
+
+ /**
+ * Get the event handle.
+ * It is a no-op in POSIX platforms and it returns
+ * ACE_INVALID_HANDLE.
+ */
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Get the implementation class.
+ virtual ACE_Proactor_Impl *implementation (void) const;
+
+ // = Factory methods for the operations
+
+ // Note that the user does not have to use or know about these
+ // methods.
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_Stream.
+ virtual ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_Stream.
+ virtual ACE_Asynch_Write_Stream_Impl *create_asynch_write_stream (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_File.
+ virtual ACE_Asynch_Read_File_Impl *create_asynch_read_file (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_File.
+ virtual ACE_Asynch_Write_File_Impl *create_asynch_write_file (void);
+
+ /// Create the correct implementation class for doing Asynch_Accept.
+ virtual ACE_Asynch_Accept_Impl *create_asynch_accept (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Transmit_File.
+ virtual ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_Dgram.
+ virtual ACE_Asynch_Read_Dgram_Impl *create_asynch_read_dgram (void);
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_Dgram.
+ virtual ACE_Asynch_Write_Dgram_Impl *create_asynch_write_dgram (void);
+
+ // = Factory methods for the results
+
+ // Note that the user does not have to use or know about these
+ // methods unless they want to "fake" results.
+
+ /// Create the correct implementation class for ACE_Asynch_Read_Stream::Result class.
+ virtual ACE_Asynch_Read_Stream_Result_Impl *create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Write_Stream::Result.
+ virtual ACE_Asynch_Write_Stream_Result_Impl *create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Read_File::Result.
+ virtual ACE_Asynch_Read_File_Result_Impl *create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Write_File::Result.
+ virtual ACE_Asynch_Write_File_Result_Impl *create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Read_Dgram::Result.
+ virtual ACE_Asynch_Read_Dgram_Result_Impl *create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Write_Dgram::Result.
+ virtual ACE_Asynch_Write_Dgram_Result_Impl *create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Accept::Result.
+ virtual ACE_Asynch_Accept_Result_Impl *create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /// Create the correct implementation class for ACE_Asynch_Transmit_File::Result.
+ virtual ACE_Asynch_Transmit_File_Result_Impl *create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+ /**
+ * Create a timer result object which can be used with the Timer
+ * mechanism of the Proactor.
+ * If <signal_number> is -1, <POSIX_SIG_Proactor> will create a
+ * Timer object with a meaningful signal number, choosing the
+ * largest signal number from the signal mask of the Proactor.
+ */
+ virtual ACE_Asynch_Result_Impl *create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+
+protected:
+
+ /**
+ * Post <how_many> completions to the completion port so that all
+ * threads can wake up. This is used in conjunction with the
+ * <run_event_loop>.
+ */
+ static int post_wakeup_completions (int how_many);
+
+ /**
+ * Post <how_many> completions to the completion port so that all
+ * threads can wake up. This is used in conjunction with the
+ * <proactor_run_event_loop>.
+ */
+ virtual int proactor_post_wakeup_completions (int how_many);
+
+ /// Set the implementation class.
+ virtual void implementation (ACE_Proactor_Impl *implementation);
+
+ /// Delegation/implementation class that all methods will be
+ /// forwarded to.
+ ACE_Proactor_Impl *implementation_;
+
+ /// Flag used to indicate whether we are responsible for cleaning up
+ /// the implementation instance.
+ int delete_implementation_;
+
+ /// Pointer to a process-wide <ACE_Proactor>.
+ static ACE_Proactor *proactor_;
+
+ /// Must delete the <proactor_> if non-0.
+ static int delete_proactor_;
+
+ /// Handles timeout events.
+ ACE_Proactor_Timer_Handler *timer_handler_;
+
+ /// This will manage the thread in the Timer_Handler.
+ ACE_Thread_Manager thr_mgr_;
+
+ /// Timer Queue.
+ TIMER_QUEUE *timer_queue_;
+
+ /// Flag on whether to delete the timer queue.
+ int delete_timer_queue_;
+
+ /// Terminate the proactor event loop.
+ sig_atomic_t end_event_loop_;
+
+ /// Number of threads in the event loop.
+ sig_atomic_t event_loop_thread_count_;
+
+ /// Mutex to protect work with lists.
+ ACE_SYNCH_MUTEX mutex_;
+
+
+private:
+ /// Deny access since member-wise won't work...
+ ACE_Proactor (const ACE_Proactor &);
+ ACE_Proactor &operator= (const ACE_Proactor &);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+#else /* NOT WIN32 or POSIX with AIO features. */
+class ACE_Export ACE_Proactor
+{
+public:
+ class Timer_Queue {};
+ ACE_Proactor (size_t /* number_of_threads */ = 0,
+ Timer_Queue * /* tq */ = 0) {}
+ virtual int handle_events (void) { return -1; }
+ virtual int handle_events (ACE_Time_Value &) { return -1; }
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static ACE_Proactor *instance (size_t threads = 0);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static ACE_Proactor *instance (ACE_Proactor *);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static void close_singleton (void);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static int run_event_loop (void);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static int run_event_loop (ACE_Time_Value &tv);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static int end_event_loop (void);
+
+ /// Placeholder to enable compilation on non-Win32 platforms
+ static sig_atomic_t event_loop_done (void);
+};
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
+
+#include "ace/post.h"
+#endif /* ACE_PROACTOR_H */
diff --git a/ace/Demux/Proactor.i b/ace/Demux/Proactor.i
new file mode 100644
index 00000000000..c4c29697efc
--- /dev/null
+++ b/ace/Demux/Proactor.i
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE int
+ACE_Proactor::run_event_loop (void)
+{
+ ACE_TRACE ("ACE_Proactor::run_event_loop");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_run_event_loop (ACE_Proactor::check_reconfiguration);
+}
+
+ACE_INLINE int
+ACE_Proactor::run_event_loop (ACE_Time_Value &tv)
+{
+ ACE_TRACE ("ACE_Proactor::run_event_loop (tv)");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_run_event_loop
+ (tv, ACE_Proactor::check_reconfiguration);
+}
+
+ACE_INLINE int
+ACE_Proactor::reset_event_loop(void)
+{
+ ACE_TRACE ("ACE_Proactor::reset_event_loop");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_reset_event_loop ();
+}
+
+ACE_INLINE int
+ACE_Proactor::end_event_loop (void)
+{
+ ACE_TRACE ("ACE_Proactor::end_event_loop");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_end_event_loop ();
+}
+
+ACE_INLINE int
+ACE_Proactor::event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Proactor::event_loop_done");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_event_loop_done ();
+}
+
+ACE_INLINE int
+ACE_Proactor::post_wakeup_completions (int how_many)
+{
+ ACE_TRACE ("ACE_Proactor::post_wakeup_completions");
+ ACE_Proactor *p = ACE_Proactor::instance ();
+
+ if (p == 0)
+ return -1;
+
+ return p->proactor_post_wakeup_completions (how_many);
+}
diff --git a/ace/Demux/Proactor_Impl.h b/ace/Demux/Proactor_Impl.h
new file mode 100644
index 00000000000..f569494667a
--- /dev/null
+++ b/ace/Demux/Proactor_Impl.h
@@ -0,0 +1,236 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Proactor_Impl.h
+ *
+ * $Id$
+ *
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_PROACTOR_IMPL_H
+#define ACE_PROACTOR_IMPL_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+// This only works on Win32 platforms and on Unix platforms supporting
+// aio calls.
+
+#include "ace/Asynch_IO.h"
+#include "ace/Reactor.h"
+
+/**
+ * @class ACE_Proactor_Impl
+ *
+ * @brief A manager for asynchronous event demultiplexing. This class
+ * is the base class for all the concrete implementation
+ * classes.
+ *
+ * See the Proactor pattern description at
+ * http://www.cs.wustl.edu/~schmidt/proactor.ps.gz for more
+ * details.
+ */
+class ACE_Export ACE_Proactor_Impl : public ACE_Event_Handler
+{
+
+public:
+ /// Virtual destruction.
+ virtual ~ACE_Proactor_Impl (void) {}
+
+ /// Close the IO completion port.
+ virtual int close (void) = 0;
+
+ /// This method adds the <handle> to the I/O completion port. This
+ /// function is a no-op function for Unix systems.
+ virtual int register_handle (ACE_HANDLE handle,
+ const void *completion_key) = 0;
+
+ /**
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time) = 0;
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (void) = 0;
+
+ /// Add wakeup dispatch threads (reinit).
+ virtual int wake_up_dispatch_threads (void) = 0;
+
+ /// Close all dispatch threads.
+ virtual int close_dispatch_threads (int wait) = 0;
+
+ /// Number of thread used as a parameter to CreatIoCompletionPort.
+ virtual size_t number_of_threads (void) const = 0;
+ virtual void number_of_threads (size_t threads) = 0;
+
+ /// Get the event handle.
+ virtual ACE_HANDLE get_handle (void) const = 0;
+
+ //
+ // = Factory methods for the operations
+ //
+ // Note that the user does not have to use or know about these
+ // methods.
+
+ /// Create the correct implementation class for doing Asynch_Read_Stream.
+ virtual ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void) = 0;
+
+ /// Create the correct implementation class for doing Asynch_Write_Stream.
+ virtual ACE_Asynch_Write_Stream_Impl *create_asynch_write_stream (void) = 0;
+
+ /// Create the correct implementation class for doing Asynch_Read_File.
+ virtual ACE_Asynch_Read_File_Impl *create_asynch_read_file (void) = 0;
+
+ /// Create the correct implementation class for doing Asynch_Write_File.
+ virtual ACE_Asynch_Write_File_Impl *create_asynch_write_file (void) = 0;
+
+ /// Create the correct implementation class for doing Asynch_Accept.
+ virtual ACE_Asynch_Accept_Impl *create_asynch_accept (void) = 0;
+
+ /// Create the correct implementation class for doing Asynch_Transmit_File.
+ virtual ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void) = 0;
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Read_Dgram.
+ virtual ACE_Asynch_Read_Dgram_Impl *create_asynch_read_dgram (void) = 0;
+
+ /// Create the correct implementation class for doing
+ /// Asynch_Write_Dgram.
+ virtual ACE_Asynch_Write_Dgram_Impl *create_asynch_write_dgram (void) = 0;
+
+ //
+ // = Factory methods for the results
+ //
+ // Note that the user does not have to use or know about these
+ // methods unless they want to "fake" results.
+
+ /// Create the correct implementation class for ACE_Asynch_Read_Stream::Result class.
+ virtual ACE_Asynch_Read_Stream_Result_Impl *create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Write_Stream::Result.
+ virtual ACE_Asynch_Write_Stream_Result_Impl *create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Read_File::Result.
+ virtual ACE_Asynch_Read_File_Result_Impl *create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Write_File::Result.
+ virtual ACE_Asynch_Write_File_Result_Impl *create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Read_Dgram::Result.
+ virtual ACE_Asynch_Read_Dgram_Result_Impl *create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Write_Dgram::Result.
+ virtual ACE_Asynch_Write_Dgram_Result_Impl *create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Accept::Result.
+ virtual ACE_Asynch_Accept_Result_Impl *create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /// Create the correct implementation class for ACE_Asynch_Transmit_File::Result.
+ virtual ACE_Asynch_Transmit_File_Result_Impl *create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN) = 0;
+
+ /**
+ * Create the correct implementation object for the Timer
+ * result. POSIX_SIG_Proactor will create a Timer object with a
+ * meaningful signal number, if you leave the signal number as 0.
+ */
+ virtual ACE_Asynch_Result_Impl *create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = 0) = 0;
+
+ /**
+ * Post <how_many> completions to the completion port so that all
+ * threads can wake up. This is used in conjunction with the
+ * <run_event_loop>.
+ */
+ virtual int post_wakeup_completions (int how_many) = 0;
+};
+
+#endif /* (ACE_WIN32 && ACE_HAS_WINCE) || ACE_HAS_AIO_CALLS */
+#include "ace/post.h"
+#endif /* ACE_PROACTOR_IMPL_H */
diff --git a/ace/Demux/QtReactor.cpp b/ace/Demux/QtReactor.cpp
new file mode 100644
index 00000000000..62f69422fb5
--- /dev/null
+++ b/ace/Demux/QtReactor.cpp
@@ -0,0 +1,435 @@
+//$Id$
+#include "ace/QtReactor.h"
+
+#if defined (ACE_HAS_QT)
+
+ACE_ALLOC_HOOK_DEFINE (ACE_QtReactor)
+
+// Must be called with lock held
+ACE_QtReactor::ACE_QtReactor (QApplication *qapp,
+ size_t size,
+ int restart,
+ ACE_Sig_Handler *handler)
+ : ACE_Select_Reactor(size, restart, handler),
+ qapp_(qapp),
+ qtime_ (0)
+
+{
+ // When the ACE_Select_Reactor is constructed it creates the notify
+ // pipe and registers it with the register_handler_i() method. The
+ // QtReactor overloads this method BUT because the
+ // register_handler_i occurs when constructing the base class
+ // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
+ // is called not the QtReactor register_handler_i(). This means
+ // that the notify pipe is registered with the ACE_Select_Reactor
+ // event handling code not the QtReactor and so notfications don't
+ // work. To get around this we simply close and re-opened the
+ // notification handler in the constructor of the QtReactor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->close ();
+
+ // Patch for MS Windows: close and open doesn't clear the read
+ // fd_set, so reset it manually
+ this->wait_set_.rd_mask_.reset ();
+
+ this->notify_handler_->open (this, 0);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_QtReactor::~ACE_QtReactor (void)
+{
+ //no-op
+}
+
+void
+ACE_QtReactor::qapplication (QApplication *qapp)
+{
+ qapp_ = qapp ;
+}
+
+int
+ACE_QtReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE( "ACE_QtReactor::wait_for_multiple_events" );
+
+ int nfound = 0;
+ do
+ {
+ max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
+ size_t width = this->handler_rep_.max_handlep1 ();
+ handle_set.rd_mask_ = this->wait_set_.rd_mask_;
+ handle_set.wr_mask_ = this->wait_set_.wr_mask_;
+ handle_set.ex_mask_ = this->wait_set_.ex_mask_;
+
+ nfound = QtWaitForMultipleEvents (width,
+ handle_set,
+ max_wait_time);
+
+ } while( nfound == -1 && this->handle_error () > 0 );
+
+ if (nfound > 0)
+ {
+#if !defined (ACE_WIN32)
+ handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_WIN32 */
+ }
+
+ return nfound;
+ // Timed out or input available
+}
+
+void
+ACE_QtReactor::timeout_event (void)
+{
+ // Deal with any timer events
+ ACE_Select_Reactor_Handle_Set handle_set;
+ this->dispatch (0, handle_set );
+
+ // Set next timeout signal
+ this->reset_timeout ();
+}
+
+void
+ACE_QtReactor::read_event (int handle)
+{
+ // Send read event
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.rd_mask_.set_bit (ACE_HANDLE(handle));
+ this->dispatch (1, dispatch_set);
+}
+
+void
+ACE_QtReactor::write_event (int handle)
+{
+ // Send write event
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.wr_mask_.set_bit (ACE_HANDLE(handle));
+ this->dispatch (1, dispatch_set);
+}
+
+void
+ACE_QtReactor::exception_event (int handle)
+{
+ // Send exception event
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ dispatch_set.ex_mask_.set_bit(ACE_HANDLE(handle));
+ dispatch (1, dispatch_set);
+}
+
+int
+ACE_QtReactor::QtWaitForMultipleEvents (int width,
+ ACE_Select_Reactor_Handle_Set &wait_set,
+ ACE_Time_Value */*max_wait_time*/)
+{
+ // Check to make sure our handle's are all usable.
+ ACE_Select_Reactor_Handle_Set temp_set = wait_set;
+
+ if (ACE_OS::select (width,
+ temp_set.rd_mask_,
+ temp_set.wr_mask_,
+ temp_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero ) == -1)
+ return -1; // Bad file arguments...
+
+ // Qt processing.
+ this->qapp_->processOneEvent () ;
+
+ // Reset the width, in case it changed during the upcalls.
+ width = handler_rep_.max_handlep1 ();
+
+ // Now actually read the result needed by the <Select_Reactor> using
+ // <select>.
+ return ACE_OS::select(width,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero);
+}
+
+int
+ACE_QtReactor::register_handler_i (ACE_HANDLE handle ,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_QtReactor::register_handler_i");
+
+ int result;
+ if ((result = ACE_Select_Reactor::register_handler_i(handle,
+ handler,
+ mask ))
+ == -1)
+ return -1;
+
+ if (ACE_BIT_ENABLED(mask, ACE_Event_Handler::READ_MASK) ||
+ ACE_BIT_ENABLED( mask, ACE_Event_Handler::ACCEPT_MASK))
+ {
+ // We check for any unused handles.
+ MAP::ITERATOR read_iter = this->read_notifier_.end ();
+ QSocketNotifier *qsock_read_notifier = 0;
+
+ // We check whether we have a data against the present
+ // handle. If so we need to unbind the data.
+ if ((this->read_notifier_.find (handle,
+ qsock_read_notifier) != -1))
+ {
+ if (qsock_read_notifier != (*read_iter).int_id_)
+ {
+ this->read_notifier_.unbind (handle,
+ qsock_read_notifier);
+ delete qsock_read_notifier;
+ }
+ }
+
+ ACE_NEW_RETURN (qsock_read_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Read),
+ -1);
+
+ this->read_notifier_.bind (handle,
+ qsock_read_notifier);
+
+ QObject::connect (qsock_read_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (read_event (int))) ;
+ }
+
+ if (ACE_BIT_ENABLED( mask, ACE_Event_Handler::WRITE_MASK) ||
+ ACE_BIT_ENABLED( mask, ACE_Event_Handler::ACCEPT_MASK) ||
+ ACE_BIT_ENABLED( mask, ACE_Event_Handler::CONNECT_MASK))
+ {
+ // We check for any unused handles.
+ MAP::ITERATOR write_iter = this->write_notifier_.end ();
+ QSocketNotifier *qsock_write_notifier = 0;
+
+ // We check whether we have a data against the present
+ // handle. If so we need to unbind the data.
+ if ((this->write_notifier_.find (handle,
+ qsock_write_notifier) != -1))
+ {
+ if (qsock_write_notifier != (*write_iter).int_id_)
+ {
+ this->write_notifier_.unbind (handle,
+ qsock_write_notifier);
+ delete qsock_write_notifier;
+ }
+ }
+
+ ACE_NEW_RETURN (qsock_write_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Write),
+ -1);
+
+ this->write_notifier_.bind (handle,
+ qsock_write_notifier);
+
+ QObject::connect (qsock_write_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (write_event (int)));
+ }
+
+ if (ACE_BIT_ENABLED( mask,
+ ACE_Event_Handler::EXCEPT_MASK))
+ {
+ // We check for any unused handles.
+ MAP::ITERATOR excpt_iter = this->exception_notifier_.end ();
+ QSocketNotifier *qsock_excpt_notifier = 0;
+
+ // We check whether we have a data against the present
+ // handle. If so we need to unbind the data.
+ if ((this->exception_notifier_.find (handle,
+ qsock_excpt_notifier) != -1))
+ {
+ if (qsock_excpt_notifier != (*excpt_iter).int_id_)
+ {
+ this->exception_notifier_.unbind (handle,
+ qsock_excpt_notifier);
+ delete qsock_excpt_notifier;
+ }
+ }
+
+ ACE_NEW_RETURN (qsock_excpt_notifier,
+ QSocketNotifier (int(handle), QSocketNotifier::Exception),
+ -1);
+
+ this->exception_notifier_.bind (handle,
+ qsock_excpt_notifier);
+
+ QObject::connect (qsock_excpt_notifier,
+ SIGNAL (activated (int)),
+ this,
+ SLOT (exception_event (int))) ;
+ }
+
+ return 0;
+}
+
+int
+ACE_QtReactor::register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::register_handler_i(handles,
+ handler,
+ mask);
+}
+
+int ACE_QtReactor::remove_handler_i (ACE_HANDLE handle ,
+ ACE_Reactor_Mask mask )
+{
+ ACE_TRACE ("ACE_QtReactor::remove_handler_i");
+
+ QSocketNotifier *qsock_notifier = 0;
+
+ // Looks for the handle in the maps and removes them.
+ MAP::ITERATOR iter = this->read_notifier_.end ();
+
+ if ((this->read_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->read_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+
+ iter = this->write_notifier_.end ();
+ if ((this->write_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->write_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+
+ iter = this->exception_notifier_.end ();
+ if ((this->exception_notifier_.find (handle,
+ qsock_notifier) != -1))
+ {
+ this->exception_notifier_.unbind (handle,
+ qsock_notifier);
+ delete qsock_notifier;
+ }
+
+ // Now let the reactor do its work.
+ return ACE_Select_Reactor::remove_handler_i (handle, mask);
+}
+
+
+int
+ACE_QtReactor::remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::remove_handler_i (handles,
+ mask);
+}
+
+// The following functions ensure that there is an Qt timeout for the
+// first timeout in the Reactor's Timer_Queue.
+
+void
+ACE_QtReactor::reset_timeout (void)
+{
+ if (this->qtime_ != 0)
+ {
+ delete this->qtime_;
+ this->qtime_ = 0;
+ }
+
+ ACE_Time_Value *max_wait_time =
+ this->timer_queue_->calculate_timeout (0) ;
+
+ if (max_wait_time)
+ {
+ ACE_NEW (this->qtime_,
+ QTimer);
+
+ QObject::connect (qtime_,
+ SIGNAL (timeout ()),
+ this,
+ SLOT (timeout_event ()));
+
+ qtime_->start(max_wait_time->msec(), 1);
+ }
+
+}
+
+
+long
+ACE_QtReactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_QtReactor::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token,
+ ace_mon,
+ this->token_,
+ -1));
+
+ long result;
+ if ((result = ACE_Select_Reactor::schedule_timer(handler,
+ arg,
+ delay_time,
+ interval)) == -1 )
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+int
+ACE_QtReactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_QtReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (handler,
+ dont_call_handle_close ) == -1 )
+ return -1 ;
+ else
+ {
+ this->reset_timeout( ) ;
+ return 0 ;
+ }
+}
+
+int ACE_QtReactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close )
+{
+ ACE_TRACE( "ACE_QtReactor::cancel_timer" ) ;
+
+ if (ACE_Select_Reactor::cancel_timer (timer_id,
+ arg,
+ dont_call_handle_close ) == -1 )
+ return -1 ;
+ else
+ {
+ this->reset_timeout( ) ;
+ return 0 ;
+ }
+}
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Map_Entry<ACE_HANDLE, QSocketNotifier *>;
+template class ACE_Map_Manager<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>;
+template class ACE_Map_Iterator_Base<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>;
+template class ACE_Map_Iterator<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>;
+template class ACE_Map_Reverse_Iterator<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Map_Entry<ACE_HANDLE, QSocketNotifier *>
+#pragma instantiate ACE_Map_Manager<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator_Base<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Reverse_Iterator<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+#endif /*ACE_HAS_QT */
diff --git a/ace/Demux/QtReactor.h b/ace/Demux/QtReactor.h
new file mode 100644
index 00000000000..7b6cb0684cb
--- /dev/null
+++ b/ace/Demux/QtReactor.h
@@ -0,0 +1,153 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file QtReactor.h
+ *
+ * $Id$
+ *
+ * @author Hamish Friedlander <ullexco@wave.co.nz>
+ * @author Balachandran Natarajan <bala@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_QTREACTOR_H
+#define ACE_QTREACTOR_H
+#include "ace/pre.h"
+
+
+#include "ace/Select_Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_QT)
+#include "ace/Map_Manager.h"
+
+// Qttoolkit specific includes.
+#include <qapplication.h>
+#include <qobject.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+
+/**
+ * @class ACE_QtReactor
+ *
+ * @brief An object-oriented event demultiplexor and event handler
+ * dispatcher that uses the Qt Library. This class declaration
+ * also uses the extension facilities provided by the Qt. So,
+ * readers of the class declaration should not be upset with
+ * the appearence of the Keywords like Q_OBJECT, private slots
+ * etc. They are specific to Qt which uses these as a call back
+ * methods implementation mechanism.
+ */
+class ACE_Export ACE_QtReactor : public QObject, public ACE_Select_Reactor
+{
+
+ Q_OBJECT
+
+ public:
+ // = Initialization and termination methods.
+ ACE_QtReactor (QApplication *qapp = NULL,
+ size_t size = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler *handler = 0);
+
+ virtual ~ACE_QtReactor (void);
+
+ void qapplication (QApplication *qapp);
+
+ // = Timer operations.
+ virtual long schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval);
+
+ virtual int cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close = 1);
+
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+ protected:
+
+ // = Register timers/handles with Qt
+
+ /// Register a single <handler>.
+ virtual int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register a set of <handlers> with Qt.
+ virtual int register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+
+ /// Remove the <handler> associated with this <handle>.
+ virtual int remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// Remove a set of <handles>.
+ virtual int remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask);
+
+ /// Wait for events to occur.
+ virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time);
+
+ virtual int QtWaitForMultipleEvents (int width,
+ ACE_Select_Reactor_Handle_Set &wait_set,
+ ACE_Time_Value *max_wait_time);
+
+ // Wait for Qt events to occur
+
+ /// Some Qt stuff that we need to have
+ QApplication *qapp_ ;
+
+ /// Typedef of a map.
+ typedef ACE_Map_Manager<ACE_HANDLE, QSocketNotifier *, ACE_Null_Mutex> MAP;
+
+ /// A notifier for a read
+ MAP read_notifier_;
+
+ /// A write notifier
+ MAP write_notifier_;
+
+ /// An exception notifier
+ MAP exception_notifier_;
+
+ /// The timer class that would provide timer-sgnals & single-shot timers
+ QTimer *qtime_ ;
+
+ private:
+ /// This method ensures there's an Qt timeout for the first timeout
+ /// in the Reactor's Timer_Queue.
+ void reset_timeout (void);
+
+ /// Deny access since member-wise won't work...
+ ACE_QtReactor (const ACE_QtReactor &);
+ ACE_QtReactor &operator= (const ACE_QtReactor &);
+
+ private slots:
+
+ // These are all part of the communication mechanism adopted in Qt.
+ /// Dispatch a Read Event
+ void read_event (int FD);
+
+ /// Dispatch a Write Event
+ void write_event (int FD);
+
+ /// Dispatch an exception event
+ void exception_event (int FD);
+
+ /// Dispach a timeout event
+ void timeout_event (void);
+};
+
+#endif /*ACE_HAS_QT */
+
+#include "ace/post.h"
+#endif /* ACE_QTREACTOR_H */
diff --git a/ace/Demux/Reactor.cpp b/ace/Demux/Reactor.cpp
new file mode 100644
index 00000000000..1ce3989b249
--- /dev/null
+++ b/ace/Demux/Reactor.cpp
@@ -0,0 +1,285 @@
+// $Id$
+
+#include "ace/Reactor.h"
+#include "ace/Reactor_Impl.h"
+#include "ace/Handle_Set.h"
+#if !defined (ACE_HAS_WINCE)
+# if !defined (ACE_LACKS_ACE_SVCCONF)
+# include "ace/Service_Config.h"
+# endif /* !ACE_LACKS_ACE_SVCCONF */
+# include "ace/WFMO_Reactor.h"
+# include "ace/Msg_WFMO_Reactor.h"
+#endif /* ! ACE_HAS_WINCE */
+#include "ace/Select_Reactor.h"
+#include "ace/TP_Reactor.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Reactor, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Reactor)
+
+ACE_Reactor::ACE_Reactor (ACE_Reactor_Impl *impl,
+ int delete_implementation)
+ : implementation_ (0),
+ delete_implementation_ (delete_implementation)
+{
+ this->implementation (impl);
+
+ if (this->implementation () == 0)
+ {
+#if !defined (ACE_WIN32) \
+ || !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0) \
+ || defined (ACE_USE_SELECT_REACTOR_FOR_REACTOR_IMPL) \
+ || defined (ACE_USE_TP_REACTOR_FOR_REACTOR_IMPL)
+ #if defined (ACE_USE_TP_REACTOR_FOR_REACTOR_IMPL)
+ ACE_NEW (impl,
+ ACE_TP_Reactor);
+ #else
+ ACE_NEW (impl,
+ ACE_Select_Reactor);
+ #endif /* ACE_USE_TP_REACTOR_FOR_REACTOR_IMPL */
+#else /* We are on Win32 and we have winsock and ACE_USE_SELECT_REACTOR_FOR_REACTOR_IMPL is not defined */
+ #if defined (ACE_USE_MSG_WFMO_REACTOR_FOR_REACTOR_IMPL)
+ ACE_NEW (impl,
+ ACE_Msg_WFMO_Reactor);
+ #else
+ ACE_NEW (impl,
+ ACE_WFMO_Reactor);
+ #endif /* ACE_USE_MSG_WFMO_REACTOR_FOR_REACTOR_IMPL */
+#endif /* !defined (ACE_WIN32) || !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0) || defined (ACE_USE_SELECT_REACTOR_FOR_REACTOR_IMPL) */
+ this->implementation (impl);
+ this->delete_implementation_ = 1;
+ }
+}
+
+ACE_Reactor::~ACE_Reactor (void)
+{
+ if (this->delete_implementation_)
+ delete this->implementation ();
+}
+
+// Process-wide ACE_Reactor.
+ACE_Reactor *ACE_Reactor::reactor_ = 0;
+
+// Controls whether the Reactor is deleted when we shut down (we can
+// only delete it safely if we created it!)
+int ACE_Reactor::delete_reactor_ = 0;
+
+ACE_Reactor *
+ACE_Reactor::instance (void)
+{
+ ACE_TRACE ("ACE_Reactor::instance");
+
+ if (ACE_Reactor::reactor_ == 0)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ACE_Reactor::reactor_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_Reactor::reactor_,
+ ACE_Reactor,
+ 0);
+ ACE_Reactor::delete_reactor_ = 1;
+ }
+ }
+ return ACE_Reactor::reactor_;
+}
+
+ACE_Reactor *
+ACE_Reactor::instance (ACE_Reactor *r,
+ int delete_reactor)
+{
+ ACE_TRACE ("ACE_Reactor::instance");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+ ACE_Reactor *t = ACE_Reactor::reactor_;
+ if (delete_reactor != 0)
+ ACE_Reactor::delete_reactor_ = 1;
+ else
+ // We can't safely delete it since we don't know who created it!
+ ACE_Reactor::delete_reactor_ = 0;
+
+ ACE_Reactor::reactor_ = r;
+ return t;
+}
+
+void
+ACE_Reactor::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Reactor::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Reactor::delete_reactor_)
+ {
+ delete ACE_Reactor::reactor_;
+ ACE_Reactor::reactor_ = 0;
+ ACE_Reactor::delete_reactor_ = 0;
+ }
+}
+
+int
+ACE_Reactor::check_reconfiguration (ACE_Reactor *)
+{
+#if !defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_ACE_SVCCONF)
+ if (ACE_Service_Config::reconfig_occurred ())
+ {
+ ACE_Service_Config::reconfigure ();
+ return 1;
+ }
+#endif /* ! ACE_HAS_WINCE || ! ACE_LACKS_ACE_SVCCONF */
+ return 0;
+}
+
+int
+ACE_Reactor::run_reactor_event_loop (REACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Reactor::run_reactor_event_loop");
+
+ if (this->reactor_event_loop_done ())
+ return 0;
+
+ while (1)
+ {
+ int result = this->implementation_->handle_events ();
+
+ if (eh != 0 && (*eh)(this))
+ continue;
+ else if (result == -1 && this->implementation_->deactivated ())
+ return 0;
+ else if (result == -1)
+ return -1;
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_Reactor::run_alertable_reactor_event_loop (REACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Reactor::run_alertable_reactor_event_loop");
+
+ if (this->reactor_event_loop_done ())
+ return 0;
+
+ while (1)
+ {
+ int result = this->implementation_->alertable_handle_events ();
+
+ if (eh != 0 && (*eh)(this))
+ continue;
+ else if (result == -1 && this->implementation_->deactivated ())
+ return 0;
+ else if (result == -1)
+ return -1;
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_Reactor::run_reactor_event_loop (ACE_Time_Value &tv,
+ REACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Reactor::run_reactor_event_loop");
+
+ if (this->reactor_event_loop_done ())
+ return 0;
+
+ while (1)
+ {
+ int result = this->implementation_->handle_events (tv);
+
+ if (eh != 0 && (*eh) (this))
+ continue;
+ else if (result == -1)
+ {
+ if (this->implementation_->deactivated ())
+ result = 0;
+ return result;
+ }
+ else if (result == 0)
+ {
+ // The <handle_events> method timed out without dispatching
+ // anything. Because of rounding and conversion errors and
+ // such, it could be that the wait loop (WFMO, select, etc.)
+ // timed out, but the timer queue said it wasn't quite ready
+ // to expire a timer. In this case, the ACE_Time_Value we
+ // passed into handle_events won't have quite been reduced
+ // to 0, and we need to go around again. If we are all the
+ // way to 0, just return, as the entire time the caller
+ // wanted to wait has been used up.
+ if (tv.usec () > 0)
+ continue;
+ return 0;
+ }
+ // Else there were some events dispatched; go around again
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_Reactor::run_alertable_reactor_event_loop (ACE_Time_Value &tv,
+ REACTOR_EVENT_HOOK eh)
+{
+ ACE_TRACE ("ACE_Reactor::run_alertable_reactor_event_loop");
+
+ if (this->reactor_event_loop_done ())
+ return 0;
+
+ for (;;)
+ {
+ int result = this->implementation_->alertable_handle_events (tv);
+
+ if (eh != 0 && (*eh)(this))
+ continue;
+ else if (result == -1 && this->implementation_->deactivated ())
+ return 0;
+ else if (result <= 0)
+ return result;
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_Reactor::end_reactor_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::end_reactor_event_loop");
+
+ this->implementation_->deactivate (1);
+
+ return 0;
+}
+
+void
+ACE_Reactor::reset_reactor_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::reset_reactor_event_loop");
+
+ this->implementation_->deactivate (0);
+}
+
+
+int
+ACE_Reactor::resumable_handler (void)
+{
+ return this->implementation ()->resumable_handler ();
+}
+
+void
+ACE_Reactor::dump (void) const
+{
+ ACE_TRACE ("ACE_Reactor::dump");
+
+ implementation_->dump ();
+}
diff --git a/ace/Demux/Reactor.h b/ace/Demux/Reactor.h
new file mode 100644
index 00000000000..d7ff7bb2a03
--- /dev/null
+++ b/ace/Demux/Reactor.h
@@ -0,0 +1,674 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Reactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_REACTOR_H
+#define ACE_REACTOR_H
+#include "ace/pre.h"
+
+class ACE_Reactor_Impl;
+
+// Need the class def for ACE_Handle_Set to compile references to it in
+// programs.
+#include "ace/OS/Handle_Set.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Timer Queue is a complicated template class. A simple forward
+// declaration will not work
+#include "ace/Timer/Timer_Queue.h"
+
+// Event_Handler.h contains the definition of ACE_Reactor_Mask
+#include "ace/Demux/Event_Handler.h"
+
+// We are using 4 or 5 signal classes, we could forward declare
+// them.... But Timer_Queue_T.h includes Signal.h, so I don't think
+// forward declaration will be useful here
+#include "ace/IPC/Signal.h"
+
+/**
+ * @class ACE_Reactor
+ *
+ * @brief The responsibility of this class is to forward all methods to
+ * its delegation/implementation class, e.g.,
+ * <ACE_Select_Reactor> or <ACE_WFMO_Reactor>.
+ */
+class ACE_Export ACE_Reactor
+{
+public:
+ /// Operations on the "ready" mask and the "dispatch" mask.
+ enum
+ {
+ /// Retrieve current value of the the "ready" mask or the
+ /// "dispatch" mask.
+ GET_MASK = 1,
+ /// Set value of bits to new mask (changes the entire mask).
+ SET_MASK = 2,
+ /// Bitwise "or" the value into the mask (only changes enabled
+ /// bits).
+ ADD_MASK = 3,
+ /// Bitwise "and" the negation of the value out of the mask (only
+ /// changes enabled bits).
+ CLR_MASK = 4
+ };
+
+ /**
+ * You can add a hook to various run_event methods and the hook will
+ * be called after handling every reactor event. If this function
+ * returns 0, <run_reactor_event_loop> will check for the return
+ * value of <handle_event>. If it is -1, the
+ * <run_reactor_event_loop> will return (pre-maturely.)
+ */
+ typedef int (*REACTOR_EVENT_HOOK)(ACE_Reactor *);
+
+ /// Get pointer to a process-wide <ACE_Reactor>.
+ static ACE_Reactor *instance (void);
+
+ /**
+ * Set pointer to a process-wide <ACE_Reactor> and return existing
+ * pointer. If <delete_reactor> != 0 then we'll delete the Reactor
+ * at destruction time.
+ */
+ static ACE_Reactor *instance (ACE_Reactor *,
+ int delete_reactor = 0);
+
+ /// Delete the dynamically allocated Singleton
+ static void close_singleton (void);
+
+ // = Singleton reactor event loop management methods.
+
+ // Note that these method ONLY work on the "Singleton Reactor,"
+ // i.e., the one returned from <ACE_Reactor::instance>.
+ /**
+ * Run the event loop until the
+ * <ACE_Reactor::handle_events/ACE_Reactor::alertable_handle_events>
+ * method returns -1 or the <end_event_loop> method is invoked.
+ * Note that this method can only be used by the singleton
+ * <ACE_Reactor::instance>. Thus, to run another reactor use
+ * <ACE_Reactor::run_reactor_event_loop>.
+ */
+ static int run_event_loop (void);
+ static int run_alertable_event_loop (void);
+
+ /**
+ * Run the event loop until the <ACE_Reactor::handle_events> or
+ * <ACE_Reactor::alertable_handle_events> methods returns -1, the
+ * <end_event_loop> method is invoked, or the <ACE_Time_Value>
+ * expires. Note that this method can only be used by the singleton
+ * <ACE_Reactor::instance>. Thus, to run another reactor use
+ * <ACE_Reactor::run_reactor_event_loop>.
+ */
+ static int run_event_loop (ACE_Time_Value &tv);
+ static int run_alertable_event_loop (ACE_Time_Value &tv);
+
+ /**
+ * Instruct the <ACE_Reactor::instance> to terminate its event loop
+ * and notifies the <ACE_Reactor::instance> so that it can wake up
+ * and close down gracefully. Note that this method can only be
+ * used by the singleton <ACE_Reactor::instance>. Thus, to
+ * terminate another reactor, use
+ * <ACE_Reactor::end_reactor_event_loop>.
+ */
+ static int end_event_loop (void);
+
+ /**
+ * Report if the <ACE_Reactor::instance>'s event loop is finished.
+ * Note that this method can only be used by the singleton
+ * <ACE_Reactor::instance>. Thus, to check another reactor use
+ * <ACE_Reactor::reactor_event_loop_done>.
+ */
+ static int event_loop_done (void);
+
+ /**
+ * Resets the <ACE_Reactor::end_event_loop_> static so that the
+ * <run_event_loop> method can be restarted. Note that this method
+ * can only be used by the singleton <ACE_Reactor::instance>. Thus,
+ * to reset another reactor use <ACE_Reactor::reset_reactor_event_loop>.
+ */
+ static void reset_event_loop (void);
+
+ /**
+ * The singleton reactor is used by the <ACE_Service_Config>.
+ * Therefore, we must check for the reconfiguration request and
+ * handle it after handling an event.
+ */
+ static int check_reconfiguration (ACE_Reactor *);
+
+ // = Reactor event loop management methods.
+
+ // These methods work with an instance of a reactor.
+ /**
+ * Run the event loop until the
+ * <ACE_Reactor::handle_events/ACE_Reactor::alertable_handle_events>
+ * method returns -1 or the <end_reactor_event_loop> method is invoked.
+ */
+ virtual int run_reactor_event_loop (REACTOR_EVENT_HOOK = 0);
+ virtual int run_alertable_reactor_event_loop (REACTOR_EVENT_HOOK = 0);
+
+ /**
+ * Run the event loop until the <ACE_Reactor::handle_events> or
+ * <ACE_Reactor::alertable_handle_events> methods returns -1, the
+ * <end_reactor_event_loop> method is invoked, or the <ACE_Time_Value>
+ * expires.
+ */
+ virtual int run_reactor_event_loop (ACE_Time_Value &tv,
+ REACTOR_EVENT_HOOK = 0);
+ virtual int run_alertable_reactor_event_loop (ACE_Time_Value &tv,
+ REACTOR_EVENT_HOOK = 0);
+
+ /**
+ * Instruct the Reactor to terminate its event loop and notifies the
+ * Reactor so that it can wake up and deactivate
+ * itself. Deactivating the Reactor would allow the Reactor to be
+ * shutdown gracefully. Internally the Reactor calls deactivate ()
+ * on the underlying implementation.
+ */
+ virtual int end_reactor_event_loop (void);
+
+ /// Indicate if the Reactor's event loop has been ended.
+ virtual int reactor_event_loop_done (void);
+
+ /// Resets the <ACE_Reactor::end_event_loop_> static so that the
+ /// <run_event_loop> method can be restarted.
+ virtual void reset_reactor_event_loop (void);
+
+ /**
+ * Create the Reactor using <implementation>. The flag
+ * <delete_implementation> tells the Reactor whether or not to
+ * delete the <implementation> on destruction.
+ */
+ ACE_Reactor (ACE_Reactor_Impl *implementation = 0,
+ int delete_implementation = 0);
+
+ /// Close down and release all resources.
+ virtual ~ACE_Reactor (void);
+
+ /**
+ * Initialize the <ACE_Reactor> to manage <max_number_of_handles>.
+ * If <restart> is non-0 then the <ACE_Reactor>'s <handle_events>
+ * method will be restarted automatically when <EINTR> occurs. If
+ * <signal_handler> or <timer_queue> are non-0 they are used as the
+ * signal handler and timer queue, respectively.
+ */
+ virtual int open (size_t max_number_of_handles,
+ int restart = 0,
+ ACE_Sig_Handler *signal_handler = 0,
+ ACE_Timer_Queue *timer_queue = 0);
+
+ /// Use a user specified signal handler instead.
+ virtual int set_sig_handler (ACE_Sig_Handler *signal_handler);
+
+ // = The following method is deprecated. Use <timer_queue> instead.
+ /// Set a user specified timer queue.
+ virtual int set_timer_queue (ACE_Timer_Queue *tq);
+
+ /// Set a user-specified timer queue.
+ /// Return the current <ACE_Timer_Queue>.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+ virtual ACE_Timer_Queue *timer_queue (void) const;
+
+ /// Close down and release all resources.
+ virtual int close (void);
+
+ // = Event loop drivers.
+
+ /**
+ * Returns non-zero if there are I/O events "ready" for dispatching,
+ * but does not actually dispatch the event handlers. By default,
+ * don't block while checking this, i.e., "poll".
+ */
+ virtual int work_pending (const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
+
+ /**
+ * This event loop driver blocks for up to <max_wait_time> before
+ * returning. It will return earlier if events occur. Note that
+ * <max_wait_time> can be 0, in which case this method blocks
+ * indefinitely until events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * Returns the total number of timers and I/O <ACE_Event_Handler>s
+ * that were dispatched, 0 if the <max_wait_time> elapsed without
+ * dispatching any handlers, or -1 if an error occurs.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, the eventloop will
+ * return when the system queues an I/O completion routine or an
+ * Asynchronous Procedure Call.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+ virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ /**
+ * This method is just like the one above, except the
+ * <max_wait_time> value is a reference and can therefore never be
+ * NULL.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, the eventloop will
+ * return when the system queues an I/O completion routine or an
+ * Asynchronous Procedure Call.
+ */
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+ virtual int alertable_handle_events (ACE_Time_Value &max_wait_time);
+
+ // = Register and remove Handlers.
+
+ /// Register <event_handler> with <mask>. The I/O handle will always
+ /// come from <get_handle> on the <event_handler>.
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register <event_handler> with <mask>. The I/O handle is provided
+ /// through the <io_handle> parameter.
+ virtual int register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+#if defined (ACE_WIN32)
+ /**
+ * Register an <event_handler> that will be notified when
+ * <event_handle> is signaled. Since no event mask is passed
+ * through this interface, it is assumed that the <event_handle>
+ * being passed in is an event handle and not an I/O handle.
+ *
+ * Originally this interface was available for all platforms, but
+ * because ACE_HANDLE is an int on non-Win32 platforms, compilers
+ * are not able to tell the difference between
+ * register_handler(ACE_Event_Handler*,ACE_Reactor_Mask) and
+ * register_handler(ACE_Event_Handler*,ACE_HANDLE). Therefore, we
+ * have restricted this method to Win32 only.
+ */
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE);
+#endif /* ACE_WIN32 */
+
+ /**
+ * Register an <event_handler> that will be notified when
+ * <event_handle> is signaled. <mask> specifies the network events
+ * that the <event_handler> is interested in.
+ */
+ virtual int register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register <event_handler> with all the <handles> in the <Handle_Set>.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register <new_sh> to handle the signal <signum> using the
+ * <new_disp>. Returns the <old_sh> that was previously registered
+ * (if any), along with the <old_disp> of the signal handler.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /// Registers <new_sh> to handle a set of signals <sigset> using the
+ /// <new_disp>.
+ virtual int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0);
+
+ /**
+ * Removes <event_handler>. Note that the I/O handle will be
+ * obtained using <get_handle> method of <event_handler> . If
+ * <mask> includes <ACE_Event_Handler::DONT_CALL> then the
+ * <handle_close> method of the <event_handler> is not invoked.
+ */
+ virtual int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes the <ACE_Event_Handler> associated with <handle>. If
+ * <mask> includes <ACE_Event_Handler::DONT_CALL> then the
+ * <handle_close> method of the associated <event_handler> is not
+ * invoked.
+ */
+ virtual int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes all handles in <handle_set>. If <mask> ==
+ * <ACE_Event_Handler::DONT_CALL> then the <handle_close> method of
+ * the associated <event_handler>s is not invoked.
+ */
+ virtual int remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Remove the ACE_Event_Handler currently associated with <signum>.
+ * Install the new disposition (if given) and return the previous
+ * disposition (if desired by the caller). Returns 0 on success and
+ * -1 if <signum> is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ /// Calls <remove_handler> for every signal in <sigset>.
+ virtual int remove_handler (const ACE_Sig_Set &sigset);
+
+ // = Suspend and resume Handlers.
+
+ /// Suspend <event_handler> temporarily. Use
+ /// <ACE_Event_Handler::get_handle> to get the handle.
+ virtual int suspend_handler (ACE_Event_Handler *event_handler);
+
+ /// Suspend <handle> temporarily.
+ virtual int suspend_handler (ACE_HANDLE handle);
+
+ /// Suspend all <handles> in handle set temporarily.
+ virtual int suspend_handler (const ACE_Handle_Set &handles);
+
+ /// Suspend all <handles> temporarily.
+ virtual int suspend_handlers (void);
+
+ /// Resume <event_handler>. Use <ACE_Event_Handler::get_handle> to
+ /// get the handle.
+ virtual int resume_handler (ACE_Event_Handler *event_handler);
+
+ /// Resume <handle>.
+ virtual int resume_handler (ACE_HANDLE handle);
+
+ /// Resume all <handles> in handle set.
+ virtual int resume_handler (const ACE_Handle_Set &handles);
+
+ /// Resume all <handles>.
+ virtual int resume_handlers (void);
+
+ /// Does the reactor allow the application to resume the handle on
+ /// its own ie. can it pass on the control of handle resumption to
+ /// the application. A positive value indicates that the handlers
+ /// are application resumable. A value of 0 indicates otherwise.
+ virtual int resumable_handler (void);
+
+ // = Timer management.
+
+ /**
+ * Schedule an ACE_Event_Handler that will expire after an amount
+ * of time. The return value of this method, a timer_id value,
+ * uniquely identifies the event_handler in the ACE_Reactor's
+ * internal list of timers.
+ * This timer_id value can be used to cancel the timer
+ * with the cancel_timer() call.
+ *
+ * @see cancel_timer()
+ * @see reset_timer_interval()
+ *
+ * @param event_handler event handler to schedule on reactor
+ * @param arg argument passed to the handle_timeout() method of event_handler
+ * @param delay time interval after which the timer will expire
+ * @param interval time interval after which the timer will be automatically rescheduled
+ * @return -1 on failure, a timer_id value on success
+ */
+ virtual long schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /**
+ * Resets the interval of the timer represented by <timer_id> to
+ * <interval>, which is specified in relative time to the current
+ * <gettimeofday>. If <interval> is equal to
+ * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
+ * timer. Returns 0 if successful, -1 if not.
+ */
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /// Cancel all <Event_Handler>s that match the address of
+ /// <event_handler>. Returns number of handlers cancelled.
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single <Event_Handler> that matches the <timer_id>
+ * value, which was returned from the schedule method. If arg is
+ * non-NULL then it will be set to point to the ``magic cookie''
+ * argument passed in when the Event_Handler was registered. This
+ * makes it possible to free up the memory and avoid memory leaks.
+ * Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ * wasn't found.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+ // = High-level Event_Handler scheduling operations
+
+ /// Add <masks_to_be_added> to the <event_handler>'s entry.
+ /// <event_handler> must already have been registered.
+ /// Note that this call does not cause the Reactor to re-examine
+ /// its set of handlers - the new masks will be noticed the next
+ /// time the Reactor waits for activity. If there is no other
+ /// activity expected, or you need immediate re-examination of
+ /// the wait masks, either call ACE_Reactor::notify after this
+ /// call, or use ACE_Reactor::register_handler instead.
+ virtual int schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Add <masks_to_be_added> to the <handle>'s entry. <event_handler>
+ /// associated with <handle> must already have been registered.
+ /// Note that this call does not cause the Reactor to re-examine
+ /// its set of handlers - the new masks will be noticed the next
+ /// time the Reactor waits for activity. If there is no other
+ /// activity expected, or you need immediate re-examination of
+ /// the wait masks, either call ACE_Reactor::notify after this
+ /// call, or use ACE_Reactor::register_handler instead.
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /// Clear <masks_to_be_cleared> from the <event_handler>'s entry.
+ /// Note that this call does not cause the Reactor to re-examine
+ /// its set of handlers - the new masks will be noticed the next
+ /// time the Reactor waits for activity. If there is no other
+ /// activity expected, or you need immediate re-examination of
+ /// the wait masks, either call ACE_Reactor::notify after this
+ /// call, or use ACE_Reactor::register_handler instead.
+ virtual int cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ /// Clear <masks_to_be_cleared> from the <handle>'s entry.
+ /// Note that this call does not cause the Reactor to re-examine
+ /// its set of handlers - the new masks will be noticed the next
+ /// time the Reactor waits for activity. If there is no other
+ /// activity expected, or you need immediate re-examination of
+ /// the wait masks, either call ACE_Reactor::notify after this
+ /// call, or use ACE_Reactor::register_handler instead.
+ virtual int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_cleared);
+
+ // = Notification methods.
+
+ /**
+ * Notify <event_handler> of <mask> event. The <ACE_Time_Value>
+ * indicates how long to blocking trying to notify. If <timeout> ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in <timeout> elapses).
+ */
+ virtual int notify (ACE_Event_Handler *event_handler = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value *tv = 0);
+
+ /**
+ * Set the maximum number of times that ACE_Reactor will
+ * iterate and dispatch the <ACE_Event_Handlers> that are passed in
+ * via the notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop. By default, this is set to
+ * -1, which means "iterate until the queue is empty." Setting this
+ * to a value like "1 or 2" will increase "fairness" (and thus
+ * prevent starvation) at the expense of slightly higher dispatching
+ * overhead.
+ */
+ virtual void max_notify_iterations (int iterations);
+
+ /**
+ * Get the maximum number of times that the ACE_Reactor will
+ * iterate and dispatch the <ACE_Event_Handlers> that are passed in
+ * via the notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop.
+ */
+ virtual int max_notify_iterations (void);
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. If <eh> == 0, all notifications for all
+ * handlers are removed (but not any notifications posted just to wake up
+ * the reactor itself). Returns the number of notifications purged.
+ * Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler *,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ // = Assorted helper methods.
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to <mask>. Return the <event_handler> associated with this
+ * <handler> if <event_handler> != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /**
+ * Check to see if <signum> is associated with a valid Event_Handler
+ * bound to a signal. Return the <event_handler> associated with
+ * this <handler> if <event_handler> != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler **event_handler = 0);
+
+ /// Returns true if Reactor has been successfully initialized, else
+ /// false.
+ virtual int initialized (void);
+
+ /// Returns the current size of the Reactor's internal descriptor
+ /// table.
+ virtual size_t size (void) const;
+
+ /// Returns a reference to the Reactor's internal lock.
+ virtual ACE_Lock &lock (void);
+
+ /// Wake up all threads in waiting in the event loop
+ virtual void wakeup_all_threads (void);
+
+ /// Transfers ownership of Reactor to the <new_owner>.
+ virtual int owner (ACE_thread_t new_owner,
+ ACE_thread_t *old_owner = 0);
+
+ /// Return the ID of the "owner" thread.
+ virtual int owner (ACE_thread_t *owner);
+
+ /// Set position of the owner thread.
+ virtual void requeue_position (int position);
+
+ /// Get position of the owner thread.
+ virtual int requeue_position (void);
+
+ /// Get the existing restart value.
+ virtual int restart (void);
+
+ /// Set a new value for restart and return the original value.
+ virtual int restart (int r);
+
+ // = Low-level wait_set mask manipulation methods.
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the
+ /// <event_handler> and <mask>.
+ virtual int mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <handle>
+ /// and <mask>.
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ // = Low-level ready_set mask manipulation methods.
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <event_handler>
+ /// and <mask>.
+ virtual int ready_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <handle> and <mask>.
+ virtual int ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// Get the implementation class
+ virtual ACE_Reactor_Impl *implementation (void) const;
+
+ /**
+ * Returns 0, if the size of the current message has been put in
+ * <size> returns -1, if not. ACE_HANDLE allows the reactor to
+ * check if the caller is valid. Used for CLASSIX Reactor
+ * implementation.
+ */
+ virtual int current_info (ACE_HANDLE handle,
+ size_t &msg_size);
+
+ /// Return 1 if we any event associations were made by the reactor
+ /// for the handles that it waits on, 0 otherwise.
+ virtual int uses_event_associations (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+protected:
+ /// Set the implementation class.
+ virtual void implementation (ACE_Reactor_Impl *implementation);
+
+ /// Delegation/implementation class that all methods will be
+ /// forwarded to.
+ ACE_Reactor_Impl *implementation_;
+
+ /// Flag used to indicate whether we are responsible for cleaning up
+ /// the implementation instance
+ int delete_implementation_;
+
+ /// Pointer to a process-wide <ACE_Reactor> singleton.
+ static ACE_Reactor *reactor_;
+
+ /// Must delete the <reactor_> singleton if non-0.
+ static int delete_reactor_;
+
+ /// Deny access since member-wise won't work...
+ ACE_Reactor (const ACE_Reactor &);
+ ACE_Reactor &operator = (const ACE_Reactor &);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Demux/Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_REACTOR_H */
diff --git a/ace/Demux/Reactor.i b/ace/Demux/Reactor.i
new file mode 100644
index 00000000000..6fb16ad8c27
--- /dev/null
+++ b/ace/Demux/Reactor.i
@@ -0,0 +1,676 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Demux/Reactor_Impl.h"
+#include "ace/OS/Handle_Set.h"
+
+ACE_INLINE ACE_Reactor_Impl *
+ACE_Reactor::implementation (void) const
+{
+ return this->implementation_;
+}
+
+ACE_INLINE void
+ACE_Reactor::implementation (ACE_Reactor_Impl *impl)
+{
+ this->implementation_ = impl;
+}
+
+ACE_INLINE int
+ACE_Reactor::current_info (ACE_HANDLE handle,
+ size_t &size)
+{
+ return this->implementation ()->current_info (handle, size);
+}
+
+// Run the event loop until the <ACE_Reactor::handle_events> method
+// returns -1 or the <end_event_loop> method is invoked.
+
+ACE_INLINE int
+ACE_Reactor::run_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::run_event_loop");
+ ACE_Reactor *r = ACE_Reactor::instance ();
+
+ if (r == 0)
+ return -1;
+
+ return r->run_reactor_event_loop (ACE_Reactor::check_reconfiguration);
+}
+
+// Run the event loop until the <ACE_Reactor::handle_events>
+// method returns -1, the <end_event_loop> method
+// is invoked, or the <ACE_Time_Value> expires.
+
+ACE_INLINE int
+ACE_Reactor::run_event_loop (ACE_Time_Value &tv)
+{
+ ACE_TRACE ("ACE_Reactor::run_event_loop");
+ ACE_Reactor *r = ACE_Reactor::instance ();
+
+ if (r == 0)
+ return -1;
+
+ return r->run_reactor_event_loop
+ (tv, ACE_Reactor::check_reconfiguration);
+}
+
+// Run the event loop until the <ACE_Reactor::alertable_handle_events> method
+// returns -1 or the <end_event_loop> method is invoked.
+
+ACE_INLINE int
+ACE_Reactor::run_alertable_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::run_alertable_event_loop");
+ ACE_Reactor *r = ACE_Reactor::instance ();
+
+ if (r == 0)
+ return -1;
+
+ return r->run_alertable_reactor_event_loop (ACE_Reactor::check_reconfiguration);
+}
+
+// Run the event loop until the <ACE_Reactor::alertable_handle_events>
+// method returns -1, the <end_event_loop> method
+// is invoked, or the <ACE_Time_Value> expires.
+
+ACE_INLINE int
+ACE_Reactor::run_alertable_event_loop (ACE_Time_Value &tv)
+{
+ ACE_TRACE ("ACE_Reactor::run_alertable_event_loop");
+ ACE_Reactor *r = ACE_Reactor::instance ();
+
+ if (r == 0)
+ return -1;
+
+ return r->run_alertable_reactor_event_loop
+ (tv, ACE_Reactor::check_reconfiguration);
+}
+
+ACE_INLINE void
+ACE_Reactor::reset_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::reset_event_loop");
+
+ ACE_Reactor::instance ()->reset_reactor_event_loop ();
+}
+
+ACE_INLINE int
+ACE_Reactor::end_event_loop (void)
+{
+ ACE_TRACE ("ACE_Reactor::end_event_loop");
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Reactor::reactor_event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Reactor::reactor_event_loop_done");
+ return this->implementation_->deactivated ();
+}
+
+ACE_INLINE int
+ACE_Reactor::event_loop_done (void)
+{
+ ACE_TRACE ("ACE_Reactor::event_loop_done");
+ return ACE_Reactor::instance ()->reactor_event_loop_done ();
+}
+
+ACE_INLINE int
+ACE_Reactor::open (size_t size,
+ int restart,
+ ACE_Sig_Handler *signal_handler,
+ ACE_Timer_Queue *timer_queue)
+{
+ return this->implementation ()->open (size,
+ restart,
+ signal_handler,
+ timer_queue);
+}
+ACE_INLINE int
+ACE_Reactor::set_sig_handler (ACE_Sig_Handler *signal_handler)
+{
+ return this->implementation ()->set_sig_handler (signal_handler);
+}
+
+ACE_INLINE int
+ACE_Reactor::timer_queue (ACE_Timer_Queue *tq)
+{
+ return this->implementation ()->timer_queue (tq);
+}
+
+ACE_INLINE int
+ACE_Reactor::set_timer_queue (ACE_Timer_Queue *tq)
+{
+ return this->timer_queue (tq);
+}
+
+ACE_INLINE ACE_Timer_Queue *
+ACE_Reactor::timer_queue (void) const
+{
+ ACE_Reactor_Impl *impl = this->implementation_;
+ return impl->timer_queue ();
+}
+
+ACE_INLINE int
+ACE_Reactor::close (void)
+{
+ return this->implementation ()->close ();
+}
+
+ACE_INLINE int
+ACE_Reactor::work_pending (const ACE_Time_Value &max_wait_time)
+{
+ return this->implementation ()->work_pending (max_wait_time);
+}
+
+ACE_INLINE int
+ACE_Reactor::handle_events (ACE_Time_Value *max_wait_time)
+{
+ return this->implementation ()->handle_events (max_wait_time);
+}
+
+ACE_INLINE int
+ACE_Reactor::alertable_handle_events (ACE_Time_Value *max_wait_time)
+{
+ return this->implementation ()->alertable_handle_events (max_wait_time);
+}
+
+ACE_INLINE int
+ACE_Reactor::handle_events (ACE_Time_Value &max_wait_time)
+{
+ return this->implementation ()->handle_events (max_wait_time);
+}
+
+ACE_INLINE int
+ACE_Reactor::alertable_handle_events (ACE_Time_Value &max_wait_time)
+{
+ return this->implementation ()->alertable_handle_events (max_wait_time);
+}
+
+
+ACE_INLINE int
+ACE_Reactor::register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->register_handler (event_handler,
+ mask);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Reactor::register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->register_handler (io_handle,
+ event_handler,
+ mask);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+#if defined (ACE_WIN32)
+
+ACE_INLINE int
+ACE_Reactor::register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->register_handler (event_handler,
+ event_handle);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+#endif /* ACE_WIN32 */
+
+ACE_INLINE int
+ACE_Reactor::register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->register_handler (event_handle,
+ io_handle,
+ event_handler,
+ mask);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Reactor::register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->register_handler (handles,
+ event_handler,
+ mask);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Reactor::register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **old_sh,
+ ACE_Sig_Action *old_disp)
+{
+ return this->implementation ()->register_handler (signum,
+ new_sh,
+ new_disp,
+ old_sh,
+ old_disp);
+}
+
+ACE_INLINE int
+ACE_Reactor::register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp)
+{
+ return this->implementation ()->register_handler (sigset,
+ new_sh,
+ new_disp);
+}
+
+ACE_INLINE int
+ACE_Reactor::remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ return this->implementation ()->remove_handler (event_handler,
+ mask);
+}
+
+ACE_INLINE int
+ACE_Reactor::remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ return this->implementation ()->remove_handler (handle,
+ mask);
+}
+
+ACE_INLINE int
+ACE_Reactor::remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask mask)
+{
+ return this->implementation ()->remove_handler (handle_set,
+ mask);
+}
+
+ACE_INLINE int
+ACE_Reactor::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int sigkey)
+{
+ return this->implementation ()->remove_handler (signum,
+ new_disp,
+ old_disp,
+ sigkey);
+}
+
+ACE_INLINE int
+ACE_Reactor::remove_handler (const ACE_Sig_Set &sigset)
+{
+ return this->implementation ()->remove_handler (sigset);
+}
+
+
+ACE_INLINE int
+ACE_Reactor::suspend_handler (ACE_Event_Handler *event_handler)
+{
+ return this->implementation ()->suspend_handler (event_handler);
+}
+
+ACE_INLINE int
+ACE_Reactor::suspend_handler (ACE_HANDLE handle)
+{
+ return this->implementation ()->suspend_handler (handle);
+}
+
+ACE_INLINE int
+ACE_Reactor::suspend_handler (const ACE_Handle_Set &handles)
+{
+ return this->implementation ()->suspend_handler (handles);
+}
+
+ACE_INLINE int
+ACE_Reactor::suspend_handlers (void)
+{
+ return this->implementation ()->suspend_handlers ();
+}
+
+ACE_INLINE int
+ACE_Reactor::resume_handler (ACE_Event_Handler *event_handler)
+{
+ return this->implementation ()->resume_handler (event_handler);
+}
+
+ACE_INLINE int
+ACE_Reactor::resume_handler (ACE_HANDLE handle)
+{
+ return this->implementation ()->resume_handler (handle);
+}
+
+ACE_INLINE int
+ACE_Reactor::resume_handler (const ACE_Handle_Set &handles)
+{
+ return this->implementation ()->resume_handler (handles);
+}
+
+ACE_INLINE int
+ACE_Reactor::resume_handlers (void)
+{
+ return this->implementation ()->resume_handlers ();
+}
+
+
+ACE_INLINE int
+ACE_Reactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Reactor::reset_timer_interval");
+
+ return this->implementation ()->reset_timer_interval
+ (timer_id,
+ interval);
+}
+
+ACE_INLINE long
+ACE_Reactor::schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delta,
+ const ACE_Time_Value &interval)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->schedule_timer (event_handler,
+ arg,
+ delta,
+ interval);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Reactor::cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close)
+{
+ return this->implementation ()->cancel_timer (event_handler,
+ dont_call_handle_close);
+}
+
+ACE_INLINE int
+ACE_Reactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ return this->implementation ()->cancel_timer (timer_id,
+ arg,
+ dont_call_handle_close);
+}
+
+
+ACE_INLINE int
+ACE_Reactor::schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added)
+{
+ // Remember the old reactor.
+ ACE_Reactor *old_reactor = event_handler->reactor ();
+
+ // Assign *this* <Reactor> to the <Event_Handler>.
+ event_handler->reactor (this);
+
+ int result = this->implementation ()->schedule_wakeup (event_handler,
+ masks_to_be_added);
+ if (result == -1)
+ // Reset the old reactor in case of failures.
+ event_handler->reactor (old_reactor);
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_Reactor::schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added)
+{
+ return implementation ()->schedule_wakeup (handle,
+ masks_to_be_added);
+}
+
+ACE_INLINE int
+ACE_Reactor::cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_cleared)
+{
+ return this->implementation ()->cancel_wakeup (event_handler,
+ masks_to_be_cleared);
+}
+
+ACE_INLINE int
+ACE_Reactor::cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_cleared)
+{
+ return this->implementation ()->cancel_wakeup (handle,
+ masks_to_be_cleared);
+}
+
+
+ACE_INLINE int
+ACE_Reactor::notify (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *tv)
+{
+ // First, try to remember this reactor in the event handler, in case
+ // the event handler goes away before the notification is delivered.
+ if (event_handler != 0 && event_handler->reactor () == 0)
+ event_handler->reactor (this);
+ return this->implementation ()->notify (event_handler,
+ mask,
+ tv);
+}
+
+ACE_INLINE void
+ACE_Reactor::max_notify_iterations (int iterations)
+{
+ this->implementation ()->max_notify_iterations (iterations);
+}
+
+ACE_INLINE int
+ACE_Reactor::max_notify_iterations (void)
+{
+ return this->implementation ()->max_notify_iterations ();
+}
+
+ACE_INLINE int
+ACE_Reactor::purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ return this->implementation ()->purge_pending_notifications (eh, mask);
+}
+
+ACE_INLINE int
+ACE_Reactor::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler)
+{
+ return this->implementation ()->handler (handle,
+ mask,
+ event_handler);
+}
+
+ACE_INLINE int
+ACE_Reactor::handler (int signum,
+ ACE_Event_Handler **event_handler)
+{
+ return this->implementation ()->handler (signum,
+ event_handler);
+}
+
+ACE_INLINE int
+ACE_Reactor::initialized (void)
+{
+ return this->implementation ()->initialized ();
+}
+
+ACE_INLINE ACE_Lock &
+ACE_Reactor::lock (void)
+{
+ return this->implementation ()->lock ();
+}
+
+ACE_INLINE void
+ACE_Reactor::wakeup_all_threads (void)
+{
+ this->implementation ()->wakeup_all_threads ();
+}
+
+ACE_INLINE int
+ACE_Reactor::owner (ACE_thread_t new_owner,
+ ACE_thread_t *old_owner)
+{
+ return this->implementation ()->owner (new_owner,
+ old_owner);
+}
+
+ACE_INLINE int
+ACE_Reactor::owner (ACE_thread_t *owner)
+{
+ return this->implementation ()->owner (owner);
+}
+
+ACE_INLINE int
+ACE_Reactor::restart (void)
+{
+ return this->implementation ()->restart ();
+}
+
+ACE_INLINE int
+ACE_Reactor::restart (int r)
+{
+ return this->implementation ()->restart (r);
+}
+
+ACE_INLINE void
+ACE_Reactor::requeue_position (int position)
+{
+ this->implementation ()->requeue_position (position);
+}
+
+ACE_INLINE int
+ACE_Reactor::requeue_position (void)
+{
+ return this->implementation ()->requeue_position ();
+}
+
+
+ACE_INLINE int
+ACE_Reactor::mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ return this->implementation ()->mask_ops (event_handler,
+ mask,
+ ops);
+}
+
+ACE_INLINE int
+ACE_Reactor::mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ return this->implementation ()->mask_ops (handle,
+ mask,
+ ops);
+}
+
+ACE_INLINE int
+ACE_Reactor::ready_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ return this->implementation ()->ready_ops (event_handler,
+ mask,
+ ops);
+}
+
+ACE_INLINE int
+ACE_Reactor::ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ return this->implementation ()->ready_ops (handle,
+ mask,
+ ops);
+}
+
+ACE_INLINE size_t
+ACE_Reactor::size (void) const
+{
+ return this->implementation ()->size ();
+}
+
+ACE_INLINE int
+ACE_Reactor::uses_event_associations (void)
+{
+ return this->implementation ()->uses_event_associations ();
+}
+
+
+
diff --git a/ace/Demux/Reactor_Impl.h b/ace/Demux/Reactor_Impl.h
new file mode 100644
index 00000000000..7ed261543bb
--- /dev/null
+++ b/ace/Demux/Reactor_Impl.h
@@ -0,0 +1,561 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Reactor_Impl.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_REACTOR_IMPL_H
+#define ACE_REACTOR_IMPL_H
+#include "ace/pre.h"
+
+// Timer Queue is a complicated template class. A simple forward
+// declaration will not work
+#include "ace/Timer/Timer_Queue.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Event_Handler.h contains the definition of ACE_Reactor_Mask
+#include "ace/Demux/Event_Handler.h"
+
+// We are using 4 or 5 signal classes, we could forward declare
+// them.... But Timer_Queue_T.h includes Signal.h, so I don't think
+// forward declaration will be useful here
+#include "ace/IPC/Signal.h"
+
+// Forward decls
+class ACE_Handle_Set;
+class ACE_Reactor_Impl;
+
+/**
+ * @class ACE_Reactor_Notify
+ *
+ * @brief Abstract class for unblocking an <ACE_Reactor_Impl> from its
+ * event loop.
+ */
+class ACE_Export ACE_Reactor_Notify : public ACE_Event_Handler
+{
+public:
+ // = Initialization and termination methods.
+ virtual int open (ACE_Reactor_Impl *,
+ ACE_Timer_Queue *timer_queue = 0,
+ int disable_notify = 0) = 0;
+ virtual int close (void) = 0;
+
+ /**
+ * Called by a thread when it wants to unblock the <Reactor_Impl>.
+ * This wakeups the <Reactor_Impl> if currently blocked. Pass over
+ * both the <Event_Handler> *and* the <mask> to allow the caller to
+ * dictate which <Event_Handler> method the <Reactor_Impl> will
+ * invoke. The <ACE_Time_Value> indicates how long to blocking
+ * trying to notify the <Reactor_Impl>. If <timeout> == 0, the
+ * caller will block until action is possible, else will wait until
+ * the relative time specified in *<timeout> elapses).
+ */
+ virtual ssize_t notify (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 0) = 0;
+
+ /// Handles pending threads (if any) that are waiting to unblock the
+ /// <Reactor_Impl>.
+ virtual int dispatch_notifications (int &number_of_active_handles,
+ ACE_Handle_Set &rd_mask) = 0;
+
+ /// Returns the ACE_HANDLE of the notify pipe on which the reactor
+ /// is listening for notifications so that other threads can unblock
+ /// the <Reactor_Impl>
+ virtual ACE_HANDLE notify_handle (void) = 0;
+
+ /// Verify whether the buffer has dispatchable info or not.
+ virtual int is_dispatchable (ACE_Notification_Buffer &buffer)= 0;
+
+ /// Handle one of the notify call on the <handle>. This could be
+ /// because of a thread trying to unblock the <Reactor_Impl>
+ virtual int dispatch_notify (ACE_Notification_Buffer &buffer) = 0;
+
+ /// Read one of the notify call on the <handle> into the
+ /// <buffer>. This could be because of a thread trying to unblock
+ /// the <Reactor_Impl>
+ virtual int read_notify_pipe (ACE_HANDLE handle,
+ ACE_Notification_Buffer &buffer) = 0;
+ /**
+ * Set the maximum number of times that the <handle_input> method
+ * will iterate and dispatch the <ACE_Event_Handlers> that are
+ * passed in via the notify queue before breaking out of the event
+ * loop. By default, this is set to -1, which means "iterate until
+ * the queue is empty." Setting this to a value like "1 or 2" will
+ * increase "fairness" (and thus prevent starvation) at the expense
+ * of slightly higher dispatching overhead.
+ */
+ virtual void max_notify_iterations (int) = 0;
+
+ /**
+ * Get the maximum number of times that the <handle_input> method
+ * will iterate and dispatch the <ACE_Event_Handlers> that are
+ * passed in via the notify queue before breaking out of its event
+ * loop.
+ */
+ virtual int max_notify_iterations (void) = 0;
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. Returns the number of notifications
+ * purged. Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) = 0;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const = 0;
+};
+
+/**
+ * @class ACE_Reactor_Impl
+ *
+ * @brief An abstract class for implementing the Reactor Pattern.
+ */
+class ACE_Export ACE_Reactor_Impl
+{
+public:
+ /// Close down and release all resources.
+ virtual ~ACE_Reactor_Impl (void) {}
+
+ /// Initialization.
+ virtual int open (size_t size,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify * = 0) = 0;
+
+ /**
+ * Returns 0, if the size of the current message has been put in
+ * <size> Returns -1, if not. ACE_HANDLE allows the reactor to
+ * check if the caller is valid.
+ */
+ virtual int current_info (ACE_HANDLE, size_t & /* size */) = 0;
+
+ /// Use a user specified signal handler instead.
+ virtual int set_sig_handler (ACE_Sig_Handler *signal_handler) = 0;
+
+ // = The following method is deprecated. Use <timer_queue> instead.
+ /// Set a user specified timer queue.
+ virtual int set_timer_queue (ACE_Timer_Queue *tq) = 0;
+
+ /// Set a user-specified timer queue.
+ /// Return the current <ACE_Timer_Queue>.
+ virtual int timer_queue (ACE_Timer_Queue *tq) = 0;
+ virtual ACE_Timer_Queue *timer_queue (void) const = 0;
+
+ /// Close down and release all resources.
+ virtual int close (void) = 0;
+
+ // = Event loop drivers.
+ /**
+ * Returns non-zero if there are I/O events "ready" for dispatching,
+ * but does not actually dispatch the event handlers. By default,
+ * don't block while checking this, i.e., "poll".
+ */
+ virtual int work_pending (const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero) = 0;
+
+ /**
+ * This event loop driver blocks for up to <max_wait_time> before
+ * returning. It will return earlier if events occur. Note that
+ * <max_wait_time> can be 0, in which case this method blocks
+ * indefinitely until events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * Returns the total number of <ACE_Event_Handler>s that were
+ * dispatched, 0 if the <max_wait_time> elapsed without dispatching
+ * any handlers, or -1 if an error occurs.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, the eventloop will
+ * return when the system queues an I/O completion routine or an
+ * Asynchronous Procedure Call.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0) = 0;
+ virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0) = 0;
+
+ /**
+ * This method is just like the one above, except the
+ * <max_wait_time> value is a reference and can therefore never be
+ * NULL.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, the eventloop will
+ * return when the system queues an I/O completion routine or an
+ * Asynchronous Procedure Call.
+ */
+ virtual int handle_events (ACE_Time_Value &max_wait_time) = 0;
+ virtual int alertable_handle_events (ACE_Time_Value &max_wait_time) = 0;
+
+ // = Event handling control.
+
+ /**
+ * Return the status of Reactor. If this function returns 0, the reactor is
+ * actively handling events. If it returns non-zero, <handling_events> and
+ * <handle_alertable_events> return -1 immediately.
+ */
+ virtual int deactivated (void) = 0;
+
+ /**
+ * Control whether the Reactor will handle any more incoming events or not.
+ * If <do_stop> == 1, the Reactor will be disabled. By default, a reactor
+ * is in active state and can be deactivated/reactived as wish.
+ */
+ virtual void deactivate (int do_stop) = 0;
+
+ // = Register and remove Handlers.
+
+ /// Register <event_handler> with <mask>. The I/O handle will always
+ /// come from <get_handle> on the <event_handler>.
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /// Register <event_handler> with <mask>. The I/O handle is provided
+ /// through the <io_handle> parameter.
+ virtual int register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+#if defined (ACE_WIN32)
+
+ // Originally this interface was available for all platforms, but
+ // because ACE_HANDLE is an int on non-Win32 platforms, compilers
+ // are not able to tell the difference between
+ // register_handler(ACE_Event_Handler*,ACE_Reactor_Mask) and
+ // register_handler(ACE_Event_Handler*,ACE_HANDLE). Therefore, we
+ // have restricted this method to Win32 only.
+
+ /**
+ * Register an <event_handler> that will be notified when
+ * <event_handle> is signaled. Since no event mask is passed
+ * through this interface, it is assumed that the <event_handle>
+ * being passed in is an event handle and not an I/O handle.
+ */
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE) = 0;
+
+#endif /* ACE_WIN32 */
+
+ /**
+ * Register an <event_handler> that will be notified when
+ * <event_handle> is signaled. <mask> specifies the network events
+ * that the <event_handler> is interested in.
+ */
+ virtual int register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /// Register <event_handler> with all the <handles> in the <Handle_Set>.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /**
+ * Register <new_sh> to handle the signal <signum> using the
+ * <new_disp>. Returns the <old_sh> that was previously registered
+ * (if any), along with the <old_disp> of the signal handler.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0) = 0;
+
+ /// Registers <new_sh> to handle a set of signals <sigset> using the
+ /// <new_disp>.
+ virtual int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0) = 0;
+
+ /**
+ * Removes <event_handler>. Note that the I/O handle will be
+ * obtained using <get_handle> method of <event_handler> . If
+ * <mask> == <ACE_Event_Handler::DONT_CALL> then the <handle_close>
+ * method of the <event_handler> is not invoked.
+ */
+ virtual int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask) = 0;
+
+ /**
+ * Removes <handle>. If <mask> == <ACE_Event_Handler::DONT_CALL>
+ * then the <handle_close> method of the associated <event_handler>
+ * is not invoked.
+ */
+ virtual int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask) = 0;
+
+ /**
+ * Removes all handles in <handle_set>. If <mask> ==
+ * <ACE_Event_Handler::DONT_CALL> then the <handle_close> method of
+ * the associated <event_handler>s is not invoked.
+ */
+ virtual int remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask mask) = 0;
+
+ /**
+ * Remove the ACE_Event_Handler currently associated with <signum>.
+ * Install the new disposition (if given) and return the previous
+ * disposition (if desired by the caller). Returns 0 on success and
+ * -1 if <signum> is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1) = 0;
+
+ /// Calls <remove_handler> for every signal in <sigset>.
+ virtual int remove_handler (const ACE_Sig_Set &sigset) = 0;
+
+ // = Suspend and resume Handlers.
+
+ /// Suspend <event_handler> temporarily. Use
+ /// <ACE_Event_Handler::get_handle> to get the handle.
+ virtual int suspend_handler (ACE_Event_Handler *event_handler) = 0;
+
+ /// Suspend <handle> temporarily.
+ virtual int suspend_handler (ACE_HANDLE handle) = 0;
+
+ /// Suspend all <handles> in handle set temporarily.
+ virtual int suspend_handler (const ACE_Handle_Set &handles) = 0;
+
+ /// Suspend all <handles> temporarily.
+ virtual int suspend_handlers (void) = 0;
+
+ /// Resume <event_handler>. Use <ACE_Event_Handler::get_handle> to
+ /// get the handle.
+ virtual int resume_handler (ACE_Event_Handler *event_handler) = 0;
+
+ /// Resume <handle>.
+ virtual int resume_handler (ACE_HANDLE handle) = 0;
+
+ /// Resume all <handles> in handle set.
+ virtual int resume_handler (const ACE_Handle_Set &handles) = 0;
+
+ /// Resume all <handles>.
+ virtual int resume_handlers (void) = 0;
+
+ /// Does the reactor allow the application to resume the handle on
+ /// its own ie. can it pass on the control of handle resumption to
+ /// the application
+ virtual int resumable_handler (void) = 0;
+
+ /// Return 1 if we any event associations were made by the reactor
+ /// for the handles that it waits on, 0 otherwise.
+ virtual int uses_event_associations (void) = 0;
+
+ // If we need to reset handles returned from accept/connect.
+
+ // = Timer management.
+
+ /**
+ * Schedule an ACE_Event_Handler that will expire after an amount
+ * of time. The return value of this method, a timer_id value,
+ * uniquely identifies the event_handler in the ACE_Reactor's
+ * internal list of timers.
+ * This timer_id value can be used to cancel the timer
+ * with the cancel_timer() call.
+ *
+ * @see cancel_timer()
+ * @see reset_timer_interval()
+ *
+ * @param event_handler event handler to schedule on reactor
+ * @param arg argument passed to the handle_timeout() method of event_handler
+ * @param delta time interval after which the timer will expire
+ * @param interval time interval after which the timer will be automatically rescheduled
+ * @return -1 on failure, a timer_id value on success
+ */
+ virtual long schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero) = 0;
+
+ /**
+ * Resets the interval of the timer represented by <timer_id> to
+ * <interval>, which is specified in relative time to the current
+ * <gettimeofday>. If <interval> is equal to
+ * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
+ * timer. Returns 0 if successful, -1 if not.
+ */
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval) = 0;
+
+ /// Cancel all Event_Handlers that match the address of
+ /// <event_handler>. Returns number of handlers cancelled.
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1) = 0;
+
+ /**
+ * Cancel the single Event_Handler that matches the <timer_id> value
+ * (which was returned from the schedule method). If arg is
+ * non-NULL then it will be set to point to the ``magic cookie''
+ * argument passed in when the Event_Handler was registered. This
+ * makes it possible to free up the memory and avoid memory leaks.
+ * Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ * wasn't found.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1) = 0;
+
+ // = High-level Event_Handler scheduling operations
+
+ /// Add <masks_to_be_added> to the <event_handler>'s entry.
+ /// <event_handler> must already have been registered.
+ virtual int schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added) = 0;
+
+ /// Add <masks_to_be_added> to the <handle>'s entry. <event_handler>
+ /// associated with <handle> must already have been registered.
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added) = 0;
+
+ /// Clear <masks_to_be_cleared> from the <event_handler>'s entry.
+ virtual int cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_cleared) = 0;
+
+ /// Clear <masks_to_be_cleared> from the <handle>'s entry.
+ virtual int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_cleared) = 0;
+
+ // = Notification methods.
+
+ /**
+ * Notify <event_handler> of <mask> event. The <ACE_Time_Value>
+ * indicates how long to blocking trying to notify. If <timeout> ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in <timeout> elapses).
+ */
+ virtual int notify (ACE_Event_Handler *event_handler = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 0) = 0;
+
+ /**
+ * Set the maximum number of times that ACE_Reactor_Impl will
+ * iterate and dispatch the <ACE_Event_Handlers> that are passed in
+ * via the notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop. By default, this is set to
+ * -1, which means "iterate until the queue is empty." Setting this
+ * to a value like "1 or 2" will increase "fairness" (and thus
+ * prevent starvation) at the expense of slightly higher dispatching
+ * overhead.
+ */
+ virtual void max_notify_iterations (int) = 0;
+
+ /**
+ * Get the maximum number of times that the ACE_Reactor_Impl will
+ * iterate and dispatch the <ACE_Event_Handlers> that are passed in
+ * via the notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop.
+ */
+ virtual int max_notify_iterations (void) = 0;
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. Returns the number of notifications
+ * purged. Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) = 0;
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to <mask>. Return the <event_handler> associated with this
+ * <handler> if <event_handler> != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0) = 0;
+
+ /**
+ * Check to see if <signum> is associated with a valid Event_Handler
+ * bound to a signal. Return the <event_handler> associated with
+ * this <handler> if <event_handler> != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler ** = 0) = 0;
+
+ /// Returns true if Reactor has been successfully initialized, else
+ /// false.
+ virtual int initialized (void) = 0;
+
+ /// Returns the current size of the Reactor's internal descriptor
+ /// table.
+ virtual size_t size (void) const = 0;
+
+ /// Returns a reference to the Reactor's internal lock.
+ virtual ACE_Lock &lock (void) = 0;
+
+ /// Wake up all threads in waiting in the event loop
+ virtual void wakeup_all_threads (void) = 0;
+
+ /// Transfers ownership of Reactor_Impl to the <new_owner>.
+ virtual int owner (ACE_thread_t new_owner, ACE_thread_t *old_owner = 0) = 0;
+
+ /// Return the ID of the "owner" thread.
+ virtual int owner (ACE_thread_t *owner) = 0;
+
+ /// Get the existing restart value.
+ virtual int restart (void) = 0;
+
+ /// Set a new value for restart and return the original value.
+ virtual int restart (int r) = 0;
+
+ /// Set position of the owner thread.
+ virtual void requeue_position (int) = 0;
+
+ /// Get position of the owner thread.
+ virtual int requeue_position (void) = 0;
+
+ // = Low-level wait_set mask manipulation methods.
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the
+ /// <event_handler> and <mask>.
+ virtual int mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops) = 0;
+
+ /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <handle>
+ /// and <mask>.
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops) = 0;
+
+ // = Low-level ready_set mask manipulation methods.
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <event_handler>
+ /// and <mask>.
+ virtual int ready_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops) = 0;
+
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <handle> and <mask>.
+ virtual int ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask,
+ int ops) = 0;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const = 0;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#include "ace/post.h"
+#endif /* ACE_REACTOR_IMPL_H */
diff --git a/ace/Demux/Reactor_Notification_Strategy.cpp b/ace/Demux/Reactor_Notification_Strategy.cpp
new file mode 100644
index 00000000000..67d713ed349
--- /dev/null
+++ b/ace/Demux/Reactor_Notification_Strategy.cpp
@@ -0,0 +1,33 @@
+#include "ace/Reactor_Notification_Strategy.h"
+#include "ace/Reactor.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Reactor_Notification_Strategy.inl"
+#endif /* __ACE_INLINE __ */
+
+ACE_RCSID(ace, Strategies, "$Id$")
+
+ACE_Reactor_Notification_Strategy::ACE_Reactor_Notification_Strategy (ACE_Reactor *reactor,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+ : ACE_Notification_Strategy (eh, mask),
+ reactor_ (reactor)
+{
+}
+
+ACE_Reactor_Notification_Strategy::~ACE_Reactor_Notification_Strategy (void)
+{
+}
+
+int
+ACE_Reactor_Notification_Strategy::notify (void)
+{
+ return this->reactor_->notify (this->eh_, this->mask_);
+}
+
+int
+ACE_Reactor_Notification_Strategy::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ return this->reactor_->notify (eh, mask);
+}
diff --git a/ace/Demux/Reactor_Notification_Strategy.h b/ace/Demux/Reactor_Notification_Strategy.h
new file mode 100644
index 00000000000..b6f5b45b28a
--- /dev/null
+++ b/ace/Demux/Reactor_Notification_Strategy.h
@@ -0,0 +1,58 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Reactor_Notification_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+#ifndef ACE_REACTOR_NOTIFICATION_STRATEGY_H
+#define ACE_REACTOR_NOTIFICATION_STRATEGY_H
+#include "ace/pre.h"
+
+#include "ace/Notification_Strategy.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Reactor_Notification_Strategy
+ *
+ * @brief Used to notify an ACE_Reactor
+ *
+ * Integrates the <ACE_Message_Queue> notification into the
+ * <ACE_Reactor::notify> method.
+ */
+class ACE_Export ACE_Reactor_Notification_Strategy : public ACE_Notification_Strategy
+{
+public:
+ ACE_Reactor_Notification_Strategy (ACE_Reactor *reactor,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// Default dtor.
+ virtual ~ACE_Reactor_Notification_Strategy (void);
+
+ virtual int notify (void);
+
+ virtual int notify (ACE_Event_Handler *,
+ ACE_Reactor_Mask mask);
+
+ // Get/Set the reactor
+ ACE_Reactor *reactor (void);
+ void reactor (ACE_Reactor *r);
+
+protected:
+ ACE_Reactor *reactor_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Reactor_Notification_Strategy.inl"
+#endif /* __ACE_INLINE __ */
+
+#include "ace/post.h"
+#endif /*ACE_REACTOR_NOTIFICATION_STRATEGY_H */
diff --git a/ace/Demux/Reactor_Notification_Strategy.inl b/ace/Demux/Reactor_Notification_Strategy.inl
new file mode 100644
index 00000000000..b9fb2811526
--- /dev/null
+++ b/ace/Demux/Reactor_Notification_Strategy.inl
@@ -0,0 +1,13 @@
+/* -*- C++ -*- */
+// $Id$
+ACE_INLINE ACE_Reactor *
+ACE_Reactor_Notification_Strategy::reactor (void)
+{
+ return this->reactor_;
+}
+
+ACE_INLINE void
+ACE_Reactor_Notification_Strategy::reactor (ACE_Reactor *r)
+{
+ this->reactor_ = r;
+}
diff --git a/ace/Demux/SUN_Proactor.cpp b/ace/Demux/SUN_Proactor.cpp
new file mode 100644
index 00000000000..b81eddd63b9
--- /dev/null
+++ b/ace/Demux/SUN_Proactor.cpp
@@ -0,0 +1,370 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/SUN_Proactor.h"
+
+#if defined (ACE_HAS_AIO_CALLS) && defined (sun)
+
+#include "ace/Task_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SUN_Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_SUN_Proactor::ACE_SUN_Proactor (size_t max_aio_operations)
+ : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
+ ACE_POSIX_Proactor::PROACTOR_SUN),
+ condition_ (mutex_)
+{
+ // To provide correct virtual calls.
+ create_notify_manager ();
+}
+
+// Destructor.
+ACE_SUN_Proactor::~ACE_SUN_Proactor (void)
+{
+ // to provide correct virtual calls
+ delete_notify_manager ();
+}
+
+int
+ACE_SUN_Proactor::handle_events (ACE_Time_Value &wait_time)
+{
+ // Decrement <wait_time> with the amount of time spent in the method
+ ACE_Countdown_Time countdown (&wait_time);
+ return this->handle_events (wait_time.msec ());
+}
+
+int
+ACE_SUN_Proactor::handle_events (void)
+{
+ return this->handle_events (ACE_INFINITE);
+}
+
+int ACE_SUN_Proactor::wait_for_start (ACE_Time_Value * abstime)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
+
+ if (num_started_aio_ != 0) // double check
+ return 0;
+
+ return condition_.wait (abstime) ;
+
+#else
+
+ return 0; // or -1 ???
+
+#endif /* ACE_MT_SAFE */
+}
+
+int
+ACE_SUN_Proactor::handle_events (u_long milli_seconds)
+{
+ int retval = 0;
+ aio_result_t *result = 0;
+
+ if (milli_seconds == ACE_INFINITE)
+ {
+ if (num_started_aio_ == 0)
+ wait_for_start (0);
+
+ result = aiowait (0);
+ }
+ else
+ {
+ struct timeval timeout;
+ timeout.tv_sec = milli_seconds / 1000;
+ timeout.tv_usec = (milli_seconds - (timeout.tv_sec * 1000)) * 1000;
+
+ if (num_started_aio_ == 0)
+ {
+ ACE_Time_Value tv (timeout);
+
+ tv += ACE_OS::gettimeofday ();
+
+ wait_for_start (&tv);
+ }
+ result = aiowait (&timeout);
+ }
+
+ if (ACE_reinterpret_cast (long, result) == 0)
+ {
+ // timeout, do nothing,
+ // we should process "post_completed" queue
+ }
+ else if (ACE_reinterpret_cast (long, result) == -1)
+ {
+ // Check errno for EINVAL,EAGAIN,EINTR ??
+ switch (errno)
+ {
+ case EINTR : // aiowait() was interrupted by a signal.
+ case EINVAL: // there are no outstanding asynchronous I/O requests.
+ break; // we should process "post_completed" queue
+
+ default: // EFAULT
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p \nNumAIO=%d\n",
+ "ACE_SUN_Proactor::handle_events: aiowait failed",
+ num_started_aio_),
+ -1);
+ }
+ }
+ else
+ {
+ int error_status = 0;
+ int return_status = 0;
+
+ ACE_POSIX_Asynch_Result *asynch_result =
+ find_completed_aio (result,
+ error_status,
+ return_status);
+
+ if (asynch_result != 0)
+ {
+ // Call the application code.
+ this->application_specific_code (asynch_result,
+ return_status, // Bytes transferred.
+ 1, // Success
+ 0, // No completion key.
+ error_status); // Error
+ retval ++ ;
+
+ }
+ }
+
+ // process post_completed results
+ retval += this->process_result_queue ();
+
+ return retval > 0 ? 1 : 0 ;
+
+}
+
+ACE_POSIX_Asynch_Result *
+ACE_SUN_Proactor::find_completed_aio (aio_result_t *result,
+ int &error_status,
+ int &return_status)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, 0));
+
+ size_t ai;
+ error_status = -1;
+ return_status= 0;
+
+ // we call find_completed_aio always with result != 0
+
+ for (ai = 0; ai < aiocb_list_max_size_; ai++)
+ if (aiocb_list_[ai] !=0 && //check for non zero
+ result == &aiocb_list_[ai]->aio_resultp)
+ break;
+
+ if (ai >= aiocb_list_max_size_) // not found
+ return 0;
+
+ error_status = result->aio_errno;
+ return_status= result->aio_return;
+
+ if (error_status == -1) // should never be
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_SUN_Proactor::find_completed_aio:"
+ "<aio_errno> has failed\n"));
+
+ return_status = 0;
+
+ // we should notify user, otherwise :
+ // memory leak for result and "hanging" user
+ // what was before :
+
+ // aiocb_list_[ai] = 0;
+ // result_list_[ai] = 0;
+ // aiocb_list_cur_size_--;
+ // return 0;
+ }
+
+ switch (error_status)
+ {
+ case EINPROGRESS : // should never be
+ case AIO_INPROGRESS : // according to SUN doc
+ return 0;
+
+ case ECANCELED : // canceled
+ return_status = 0;
+ break;
+
+ case 0 : // no error
+ if (return_status == -1) // return_status should be >= 0
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::%p\n",
+ "ACE_SUN_Proactor::find_completed_aio:"
+ "<aio_return> failed\n"));
+
+ return_status = 0; // zero bytes transferred
+ }
+ break;
+
+ default : // other errors
+ if (return_status == -1) // normal status for I/O Error
+ return_status = 0; // zero bytes transferred
+ break;
+ }
+
+ ACE_POSIX_Asynch_Result *asynch_result = result_list_[ai];
+
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ aiocb_list_cur_size_--;
+
+ num_started_aio_ --;
+
+ start_deferred_aio ();
+ //make attempt to start deferred AIO
+ //It is safe as we are protected by mutex_
+
+ return asynch_result;
+}
+
+// start_aio has new return codes
+// 0 successful start
+// 1 try later, OS queue overflow
+// -1 invalid request and other errors
+
+int
+ACE_SUN_Proactor::start_aio (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_TRACE ("ACE_SUN_Proactor::start_aio");
+
+ int ret_val;
+ const ACE_TCHAR *ptype;
+
+ // Start IO
+
+ switch (result->aio_lio_opcode)
+ {
+ case LIO_READ :
+ ptype = "read";
+ ret_val = aioread (result->aio_fildes,
+ (char *) result->aio_buf,
+ result->aio_nbytes,
+ result->aio_offset,
+ SEEK_SET,
+ &result->aio_resultp);
+ break;
+
+ case LIO_WRITE :
+ ptype = "write";
+ ret_val = aiowrite (result->aio_fildes,
+ (char *) result->aio_buf,
+ result->aio_nbytes,
+ result->aio_offset,
+ SEEK_SET,
+ &result->aio_resultp);
+ break;
+
+ default:
+ ptype = "?????";
+ ret_val = -1;
+ break;
+ }
+
+ if (ret_val == 0)
+ {
+ num_started_aio_ ++ ;
+ if (num_started_aio_ == 1) // wake up condition
+ condition_.broadcast ();
+ }
+ else // if (ret_val == -1)
+ {
+ if (errno == EAGAIN) //try later, it will be deferred AIO
+ ret_val = 1 ;
+ else
+ ACE_ERROR ((LM_ERROR,
+ "%N:%l:(%P | %t)::start_aio: aio%s %p\n",
+ ptype,
+ "queueing failed\n"));
+ }
+
+ return ret_val;
+}
+
+int
+ACE_SUN_Proactor::cancel_aiocb (ACE_POSIX_Asynch_Result *result)
+{
+ ACE_TRACE ("ACE_SUN_Proactor::cancel_aiocb");
+ int rc = ::aiocancel (& result->aio_resultp);
+
+ if (rc == 0) // AIO_CANCELED
+ return 0;
+
+ return 2;
+}
+
+int
+ACE_SUN_Proactor::cancel_aio (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SUN_Proactor::cancel_aio");
+
+ int num_total = 0;
+ int num_cancelled = 0;
+
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1));
+
+ size_t ai = 0;
+
+ for (ai = 0; ai < aiocb_list_max_size_; ai++)
+ {
+ if (result_list_[ai] == 0) //skip empty slot
+ continue ;
+
+ if (result_list_[ai]->aio_fildes != handle) //skip not our slot
+ continue ;
+
+ num_total++ ;
+
+ ACE_POSIX_Asynch_Result *asynch_result = result_list_[ai];
+
+ int rc_cancel = 0 ; // let assume canceled
+
+ if (aiocb_list_ [ai] == 0) //deferred aio
+ num_deferred_aiocb_--;
+ else //cancel started aio
+ rc_cancel = this->cancel_aiocb (asynch_result);
+
+ if (rc_cancel == 0)
+ {
+ num_cancelled ++ ;
+
+ aiocb_list_[ai] = 0;
+ result_list_[ai] = 0;
+ aiocb_list_cur_size_--;
+
+ // after aiocancel Sun does not notify us
+ // so we should send notification
+ // to save POSIX behavoir.
+ // Also we should do this for deffered aio's
+
+ asynch_result->set_error (ECANCELED);
+ asynch_result->set_bytes_transferred (0);
+ this->putq_result (asynch_result);
+ }
+ }
+
+ } // release mutex_
+
+
+ if (num_total == 0)
+ return 1; // ALLDONE
+
+ if (num_cancelled == num_total)
+ return 0; // CANCELLED
+
+ return 2; // NOT CANCELLED
+}
+
+#endif /* ACE_HAS_AIO_CALLS && sun */
diff --git a/ace/Demux/SUN_Proactor.h b/ace/Demux/SUN_Proactor.h
new file mode 100644
index 00000000000..ae01690d731
--- /dev/null
+++ b/ace/Demux/SUN_Proactor.h
@@ -0,0 +1,121 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SUN_Proactor.h
+ *
+ * $Id$
+ *
+ * @author Alexander Libman <alibman@baltimore.com>
+ */
+//=============================================================================
+
+#ifndef ACE_SUN_PROACTOR_H
+#define ACE_SUN_PROACTOR_H
+
+#include "ace/POSIX_Proactor.h"
+
+#if defined (ACE_HAS_AIO_CALLS) && defined (sun)
+
+#include "sys/asynch.h" // Sun native aio calls
+
+/**
+ * @class ACE_SUN_Proactor
+ *
+ * @brief Implementation of the fast and reliable Proactor
+ * for SunOS 5.6, 5.7, etc.
+ *
+ * This proactor, based on <ACE_POSIX_AIOCB_Proactor>,
+ * works with Sun native interface for aio calls.
+ * POSIX_API Native SUN_API
+ * aio_read aioread
+ * aio_write aiowrite
+ * aio_suspend aiowait
+ * aio_error aio_result_t.errno
+ * aio_return aio_result_t.return
+ * On Solaris, the Sun <aio*()> native implementation is more
+ * reliable and efficient than POSIX <aio_*()> implementation.
+ * There is a problem of lost RT signals with POSIX, if we start
+ * more than SIGQUEUEMAX asynchronous operations at the same
+ * time.
+ * The Sun <aiocb> it is not the standard POSX <aiocb>, instead,
+ * it has the following structure:
+ * typedef struct aiocb
+ * {
+ * int aio_fildes; File descriptor
+ * void *aio_buf; buffer location
+ * size_t aio_nbytes; length of transfer
+ * off_t aio_offset; file offset
+ * int aio_reqprio; request priority offset
+ * sigevent aio_sigevent; signal number and offset
+ * int aio_lio_opcode; listio operation
+ * aio_result_t aio_resultp; results
+ * int aio_state; state flag for List I/O
+ * int aio__pad[1]; extension padding
+ * };
+ */
+class ACE_Export ACE_SUN_Proactor : public ACE_POSIX_AIOCB_Proactor
+{
+
+public:
+ virtual Proactor_Type get_impl_type (void);
+
+ /// Destructor.
+ virtual ~ACE_SUN_Proactor (void);
+
+ /// Constructor defines max number asynchronous operations that can
+ /// be started at the same time.
+ ACE_SUN_Proactor (size_t max_aio_operations = ACE_AIO_DEFAULT_SIZE);
+
+protected:
+ /**
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time);
+
+ /**
+ * Dispatch a single set of events. If <milli_seconds> elapses
+ * before any events occur, return 0. Return 1 if a completion is
+ * dispatched. Return -1 on errors.
+ */
+ virtual int handle_events (u_long milli_seconds);
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (void);
+
+ /// From ACE_POSIX_AIOCB_Proactor.
+ virtual int start_aio (ACE_POSIX_Asynch_Result *result);
+
+ /// Extract the results of aio.
+ ACE_POSIX_Asynch_Result *find_completed_aio (aio_result_t *result,
+ int &error_status,
+ int &return_status);
+
+ /// From ACE_POSIX_AIOCB_Proactor.
+ /// Attempt to cancel running request
+ virtual int cancel_aiocb (ACE_POSIX_Asynch_Result *result);
+ virtual int cancel_aio (ACE_HANDLE handle);
+
+ /// Specific Sun aiowait
+ int wait_for_start (ACE_Time_Value * abstime);
+
+ /// Condition variable .
+ /// used to wait the first AIO start
+ ACE_SYNCH_CONDITION condition_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/SUN_Proactor.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_AIO_CALLS && sun */
+#endif /* ACE_SUN_PROACTOR_H*/
diff --git a/ace/Demux/SUN_Proactor.i b/ace/Demux/SUN_Proactor.i
new file mode 100644
index 00000000000..545841223aa
--- /dev/null
+++ b/ace/Demux/SUN_Proactor.i
@@ -0,0 +1,8 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+ACE_POSIX_Proactor::Proactor_Type ACE_SUN_Proactor::get_impl_type (void)
+{
+ return PROACTOR_SUN;
+}
diff --git a/ace/Demux/Select_Reactor.cpp b/ace/Demux/Select_Reactor.cpp
new file mode 100644
index 00000000000..fe5be69789f
--- /dev/null
+++ b/ace/Demux/Select_Reactor.cpp
@@ -0,0 +1,44 @@
+// $Id$
+
+#include "ace/Select_Reactor.h"
+
+ACE_RCSID(ace, Select_Reactor, "$Id$")
+
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION)
+template class ACE_Select_Reactor_Token_T<ACE_Local_Mutex>;
+template class ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >;
+template class ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >;
+template class ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >;
+# else
+template class ACE_Select_Reactor_Token_T<ACE_Token>;
+template class ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Token> >;
+template class ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Token> >;
+template class ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Token> >;
+# endif /* ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION */
+# else
+template class ACE_Select_Reactor_Token_T<ACE_Noop_Token>;
+template class ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >;
+template class ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >;
+# endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION)
+# pragma instantiate ACE_Select_Reactor_Token_T<ACE_Local_Mutex>
+# pragma instantiate ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >
+# pragma instantiate ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >
+# pragma instantiate ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Local_Mutex> >
+# else
+# pragma instantiate ACE_Select_Reactor_Token_T<ACE_Token>
+# pragma instantiate ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Token> >
+# pragma instantiate ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Token> >
+# pragma instantiate ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Token> >
+# endif /* ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION */
+# else
+# pragma instantiate ACE_Select_Reactor_Token_T<ACE_Noop_Token>
+# pragma instantiate ACE_Select_Reactor_T< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >
+# pragma instantiate ACE_Lock_Adapter< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >
+# endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Demux/Select_Reactor.h b/ace/Demux/Select_Reactor.h
new file mode 100644
index 00000000000..ab94d6c7f40
--- /dev/null
+++ b/ace/Demux/Select_Reactor.h
@@ -0,0 +1,68 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Select_Reactor.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SELECT_REACTOR_H
+#define ACE_SELECT_REACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+#if defined (ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION)
+#include "ace/Local_Tokens.h"
+typedef ACE_Select_Reactor_Token_T<ACE_Local_Mutex> ACE_Select_Reactor_Token;
+#else
+typedef ACE_Select_Reactor_Token_T<ACE_Token> ACE_Select_Reactor_Token;
+#endif /* ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION */
+#else
+typedef ACE_Select_Reactor_Token_T<ACE_Noop_Token> ACE_Select_Reactor_Token;
+#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
+
+typedef ACE_Select_Reactor_T<ACE_Select_Reactor_Token> ACE_Select_Reactor;
+ACE_TEMPLATE_SPECIALIZATION
+
+/**
+ * @class ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >
+ *
+ * @brief Template specialization of <ACE_Guard> for the
+ * <ACE_Null_Mutex>.
+ *
+ * This specialization is useful since it helps to speedup
+ * performance of the "Null_Mutex" considerably.
+ */
+class ACE_Export ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Noop_Token> >
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Guard (ACE_Select_Reactor_Token_T<ACE_Noop_Token> &) {}
+ ACE_Guard (ACE_Select_Reactor_Token_T<ACE_Noop_Token> &, int) {}
+ ~ACE_Guard (void) {}
+
+ int acquire (void) { return 0; }
+ int tryacquire (void) { return 0; }
+ int release (void) { return 0; }
+ int locked (void) { return 1; }
+ int remove (void) { return 0; }
+ void dump (void) const {}
+
+private:
+ // = Prevent assignment and initialization.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Noop_Token> > &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Guard (const ACE_Guard< ACE_Select_Reactor_Token_T<ACE_Noop_Token> > &))
+};
+
+#include "ace/post.h"
+#endif /* ACE_SELECT_REACTOR_H */
diff --git a/ace/Demux/Select_Reactor_Base.cpp b/ace/Demux/Select_Reactor_Base.cpp
new file mode 100644
index 00000000000..eb129a75073
--- /dev/null
+++ b/ace/Demux/Select_Reactor_Base.cpp
@@ -0,0 +1,1135 @@
+// $Id$
+
+#include "ace/Select_Reactor_Base.h"
+#include "ace/Reactor.h"
+#include "ace/Thread.h"
+#include "ace/Synch_T.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_Base.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Select_Reactor_Base, "$Id$")
+
+
+#if defined (ACE_WIN32)
+#define ACE_SELECT_REACTOR_HANDLE(H) (this->event_handlers_[(H)].handle_)
+#define ACE_SELECT_REACTOR_EVENT_HANDLER(THIS,H) ((THIS)->event_handlers_[(H)].event_handler_)
+#else
+#define ACE_SELECT_REACTOR_HANDLE(H) (H)
+#define ACE_SELECT_REACTOR_EVENT_HANDLER(THIS,H) ((THIS)->event_handlers_[(H)])
+#endif /* ACE_WIN32 */
+
+// Performs sanity checking on the ACE_HANDLE.
+
+int
+ACE_Select_Reactor_Handler_Repository::invalid_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::invalid_handle");
+#if defined (ACE_WIN32)
+ // It's too expensive to perform more exhaustive validity checks on
+ // Win32 due to the way that they implement SOCKET HANDLEs.
+ if (handle == ACE_INVALID_HANDLE)
+#else /* !ACE_WIN32 */
+ if (handle < 0 || handle >= this->max_size_)
+#endif /* ACE_WIN32 */
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+// Performs sanity checking on the ACE_HANDLE.
+
+int
+ACE_Select_Reactor_Handler_Repository::handle_in_range (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::handle_in_range");
+#if defined (ACE_WIN32)
+ // It's too expensive to perform more exhaustive validity checks on
+ // Win32 due to the way that they implement SOCKET HANDLEs.
+ if (handle != ACE_INVALID_HANDLE)
+#else /* !ACE_WIN32 */
+ if (handle >= 0 && handle < this->max_handlep1_)
+#endif /* ACE_WIN32 */
+ return 1;
+ else
+ {
+ errno = EINVAL;
+ return 0;
+ }
+}
+
+size_t
+ACE_Select_Reactor_Handler_Repository::max_handlep1 (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::max_handlep1");
+
+ return this->max_handlep1_;
+}
+
+int
+ACE_Select_Reactor_Handler_Repository::open (size_t size)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::open");
+ this->max_size_ = size;
+ this->max_handlep1_ = 0;
+
+#if defined (ACE_WIN32)
+ // Try to allocate the memory.
+ ACE_NEW_RETURN (this->event_handlers_,
+ ACE_Event_Tuple[size],
+ -1);
+
+ // Initialize the ACE_Event_Handler * to { ACE_INVALID_HANDLE, 0 }.
+ for (size_t h = 0; h < size; h++)
+ {
+ ACE_SELECT_REACTOR_HANDLE (h) = ACE_INVALID_HANDLE;
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, h) = 0;
+ }
+#else
+ // Try to allocate the memory.
+ ACE_NEW_RETURN (this->event_handlers_,
+ ACE_Event_Handler *[size],
+ -1);
+
+ // Initialize the ACE_Event_Handler * to NULL.
+ for (size_t h = 0; h < size; h++)
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, h) = 0;
+#endif /* ACE_WIN32 */
+
+ // Try to increase the number of handles if <size> is greater than
+ // the current limit.
+ return ACE::set_handle_limit (size);
+}
+
+// Initialize a repository of the appropriate <size>.
+
+ACE_Select_Reactor_Handler_Repository::ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl &select_reactor)
+ : select_reactor_ (select_reactor),
+ max_size_ (0),
+ max_handlep1_ (0),
+ event_handlers_ (0)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::ACE_Select_Reactor_Handler_Repository");
+}
+
+int
+ACE_Select_Reactor_Handler_Repository::unbind_all (void)
+{
+ // Unbind all of the <handle, ACE_Event_Handler>s.
+ for (int handle = 0;
+ handle < this->max_handlep1_;
+ handle++)
+ this->unbind (ACE_SELECT_REACTOR_HANDLE (handle),
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ return 0;
+}
+
+int
+ACE_Select_Reactor_Handler_Repository::close (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::close");
+
+ if (this->event_handlers_ != 0)
+ {
+ this->unbind_all ();
+
+ delete [] this->event_handlers_;
+ this->event_handlers_ = 0;
+ }
+ return 0;
+}
+
+// Return the <ACE_Event_Handler *> associated with the <handle>.
+
+ACE_Event_Handler *
+ACE_Select_Reactor_Handler_Repository::find (ACE_HANDLE handle,
+ size_t *index_p)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::find");
+
+ ACE_Event_Handler *eh = 0;
+ ssize_t i;
+
+ // Only bother to search for the <handle> if it's in range.
+ if (this->handle_in_range (handle))
+ {
+#if defined (ACE_WIN32)
+ i = 0;
+
+ for (; i < this->max_handlep1_; i++)
+ if (ACE_SELECT_REACTOR_HANDLE (i) == handle)
+ {
+ eh = ACE_SELECT_REACTOR_EVENT_HANDLER (this, i);
+ break;
+ }
+#else
+ i = handle;
+
+ eh = ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle);
+#endif /* ACE_WIN32 */
+ }
+ else
+ // g++ can't figure out that <i> won't be used below if the handle
+ // is out of range, so keep it happy by defining <i> here . . .
+ i = 0;
+
+ if (eh != 0)
+ {
+ if (index_p != 0)
+ *index_p = i;
+ }
+ else
+ errno = ENOENT;
+
+ return eh;
+}
+
+// Bind the <ACE_Event_Handler *> to the <ACE_HANDLE>.
+
+int
+ACE_Select_Reactor_Handler_Repository::bind (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::bind");
+
+ if (handle == ACE_INVALID_HANDLE)
+ handle = event_handler->get_handle ();
+
+ if (this->invalid_handle (handle))
+ return -1;
+
+#if defined (ACE_WIN32)
+ int assigned_slot = -1;
+
+ for (ssize_t i = 0; i < this->max_handlep1_; i++)
+ {
+ // Found it, so let's just reuse this location.
+ if (ACE_SELECT_REACTOR_HANDLE (i) == handle)
+ {
+ assigned_slot = i;
+ break;
+ }
+ // Here's the first free slot, so let's take it.
+ else if (ACE_SELECT_REACTOR_HANDLE (i) == ACE_INVALID_HANDLE
+ && assigned_slot == -1)
+ assigned_slot = i;
+ }
+
+ if (assigned_slot > -1)
+ // We found a free spot, let's reuse it.
+ {
+ ACE_SELECT_REACTOR_HANDLE (assigned_slot) = handle;
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, assigned_slot) = event_handler;
+ }
+ else if (this->max_handlep1_ < this->max_size_)
+ {
+ // Insert at the end of the active portion.
+ ACE_SELECT_REACTOR_HANDLE (this->max_handlep1_) = handle;
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, this->max_handlep1_) = event_handler;
+ this->max_handlep1_++;
+ }
+ else
+ {
+ // No more room at the inn!
+ errno = ENOMEM;
+ return -1;
+ }
+#else
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle) = event_handler;
+
+ if (this->max_handlep1_ < handle + 1)
+ this->max_handlep1_ = handle + 1;
+#endif /* ACE_WIN32 */
+
+ // Add the <mask> for this <handle> in the Select_Reactor's wait_set.
+ this->select_reactor_.bit_ops (handle,
+ mask,
+ this->select_reactor_.wait_set_,
+ ACE_Reactor::ADD_MASK);
+
+ // Note the fact that we've changed the state of the <wait_set_>,
+ // which is used by the dispatching loop to determine whether it can
+ // keep going or if it needs to reconsult select().
+ this->select_reactor_.state_changed_ = 1;
+
+ return 0;
+}
+
+// Remove the binding of <ACE_HANDLE>.
+
+int
+ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::unbind");
+
+ size_t slot;
+ ACE_Event_Handler *eh = this->find (handle, &slot);
+
+ if (eh == 0)
+ return -1;
+
+ // Clear out the <mask> bits in the Select_Reactor's wait_set.
+ this->select_reactor_.bit_ops (handle,
+ mask,
+ this->select_reactor_.wait_set_,
+ ACE_Reactor::CLR_MASK);
+
+ // And suspend_set.
+ this->select_reactor_.bit_ops (handle,
+ mask,
+ this->select_reactor_.suspend_set_,
+ ACE_Reactor::CLR_MASK);
+
+ // Note the fact that we've changed the state of the <wait_set_>,
+ // which is used by the dispatching loop to determine whether it can
+ // keep going or if it needs to reconsult select().
+ this->select_reactor_.state_changed_ = 1;
+
+ // Close down the <Event_Handler> unless we've been instructed not
+ // to.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)
+ eh->handle_close (handle, mask);
+
+ // If there are no longer any outstanding events on this <handle>
+ // then we can totally shut down the Event_Handler.
+ if (this->select_reactor_.wait_set_.rd_mask_.is_set (handle) == 0
+ && this->select_reactor_.wait_set_.wr_mask_.is_set (handle) == 0
+ && this->select_reactor_.wait_set_.ex_mask_.is_set (handle) == 0)
+#if defined (ACE_WIN32)
+ {
+ ACE_SELECT_REACTOR_HANDLE (slot) = ACE_INVALID_HANDLE;
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, slot) = 0;
+
+ if (this->max_handlep1_ == (int) slot + 1)
+ {
+ // We've deleted the last entry (i.e., i + 1 == the current
+ // size of the array), so we need to figure out the last
+ // valid place in the array that we should consider in
+ // subsequent searches.
+
+ int i;
+
+ for (i = this->max_handlep1_ - 1;
+ i >= 0 && ACE_SELECT_REACTOR_HANDLE (i) == ACE_INVALID_HANDLE;
+ i--)
+ continue;
+
+ this->max_handlep1_ = i + 1;
+ }
+ }
+#else
+ {
+ ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle) = 0;
+
+ if (this->max_handlep1_ == handle + 1)
+ {
+ // We've deleted the last entry, so we need to figure out
+ // the last valid place in the array that is worth looking
+ // at.
+ ACE_HANDLE wait_rd_max = this->select_reactor_.wait_set_.rd_mask_.max_set ();
+ ACE_HANDLE wait_wr_max = this->select_reactor_.wait_set_.wr_mask_.max_set ();
+ ACE_HANDLE wait_ex_max = this->select_reactor_.wait_set_.ex_mask_.max_set ();
+
+ ACE_HANDLE suspend_rd_max = this->select_reactor_.suspend_set_.rd_mask_.max_set ();
+ ACE_HANDLE suspend_wr_max = this->select_reactor_.suspend_set_.wr_mask_.max_set ();
+ ACE_HANDLE suspend_ex_max = this->select_reactor_.suspend_set_.ex_mask_.max_set ();
+
+ // Compute the maximum of six values.
+ this->max_handlep1_ = wait_rd_max;
+ if (this->max_handlep1_ < wait_wr_max)
+ this->max_handlep1_ = wait_wr_max;
+ if (this->max_handlep1_ < wait_ex_max)
+ this->max_handlep1_ = wait_ex_max;
+
+ if (this->max_handlep1_ < suspend_rd_max)
+ this->max_handlep1_ = suspend_rd_max;
+ if (this->max_handlep1_ < suspend_wr_max)
+ this->max_handlep1_ = suspend_wr_max;
+ if (this->max_handlep1_ < suspend_ex_max)
+ this->max_handlep1_ = suspend_ex_max;
+
+ this->max_handlep1_++;
+ }
+ }
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+ACE_Select_Reactor_Handler_Repository_Iterator::ACE_Select_Reactor_Handler_Repository_Iterator
+ (const ACE_Select_Reactor_Handler_Repository *s)
+ : rep_ (s),
+ current_ (-1)
+{
+ this->advance ();
+}
+
+// Pass back the <next_item> that hasn't been seen in the Set.
+// Returns 0 when all items have been seen, else 1.
+
+int
+ACE_Select_Reactor_Handler_Repository_Iterator::next (ACE_Event_Handler *&next_item)
+{
+ int result = 1;
+
+ if (this->current_ >= this->rep_->max_handlep1_)
+ result = 0;
+ else
+ next_item = ACE_SELECT_REACTOR_EVENT_HANDLER (this->rep_,
+ this->current_);
+ return result;
+}
+
+int
+ACE_Select_Reactor_Handler_Repository_Iterator::done (void) const
+{
+ return this->current_ >= this->rep_->max_handlep1_;
+}
+
+// Move forward by one element in the set.
+
+int
+ACE_Select_Reactor_Handler_Repository_Iterator::advance (void)
+{
+ if (this->current_ < this->rep_->max_handlep1_)
+ this->current_++;
+
+ while (this->current_ < this->rep_->max_handlep1_)
+ if (ACE_SELECT_REACTOR_EVENT_HANDLER (this->rep_, this->current_) != 0)
+ return 1;
+ else
+ this->current_++;
+
+ return this->current_ < this->rep_->max_handlep1_;
+}
+
+// Dump the state of an object.
+
+void
+ACE_Select_Reactor_Handler_Repository_Iterator::dump (void) const
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository_Iterator::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("rep_ = %u"), this->rep_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("current_ = %d"), this->current_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_Select_Reactor_Handler_Repository::dump (void) const
+{
+ ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%t) max_handlep1_ = %d, max_size_ = %d\n"),
+ this->max_handlep1_, this->max_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("[")));
+
+ ACE_Event_Handler *eh = 0;
+
+ for (ACE_Select_Reactor_Handler_Repository_Iterator iter (this);
+ iter.next (eh) != 0;
+ iter.advance ())
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" (eh = %x, eh->handle_ = %d)"),
+ eh, eh->get_handle ()));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" ]")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Select_Reactor_Handler_Repository_Iterator)
+
+ACE_Select_Reactor_Notify::ACE_Select_Reactor_Notify (void)
+ : max_notify_iterations_ (-1)
+{
+}
+
+void
+ACE_Select_Reactor_Notify::max_notify_iterations (int iterations)
+{
+ // Must always be > 0 or < 0 to optimize the loop exit condition.
+ if (iterations == 0)
+ iterations = 1;
+
+ this->max_notify_iterations_ = iterations;
+}
+
+int
+ACE_Select_Reactor_Notify::max_notify_iterations (void)
+{
+ return this->max_notify_iterations_;
+}
+
+// purge_pending_notifications
+// Removes all entries from the notify_queue_ and each one that
+// matches <eh> is put on the free_queue_. The rest are saved on a
+// local queue and copied back to the notify_queue_ at the end.
+// Returns the number of entries removed. Returns -1 on error.
+// ACE_NOTSUP_RETURN if ACE_HAS_REACTOR_NOTIFICATION_QUEUE is not defined.
+int
+ACE_Select_Reactor_Notify::purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask )
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::purge_pending_notifications");
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ if (this->notify_queue_.is_empty ())
+ return 0;
+
+ ACE_Notification_Buffer *temp;
+ ACE_Unbounded_Queue <ACE_Notification_Buffer *> local_queue;
+
+ size_t queue_size = this->notify_queue_.size ();
+ int number_purged = 0;
+ size_t i;
+ for (i = 0; i < queue_size; ++i)
+ {
+ if (-1 == this->notify_queue_.dequeue_head (temp))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("dequeue_head")),
+ -1);
+
+ // If this is not a Reactor notify (it is for a particular handler),
+ // and it matches the specified handler (or purging all),
+ // and applying the mask would totally eliminate the notification, then
+ // release it and count the number purged.
+ if ((0 != temp->eh_) &&
+ (0 == eh || eh == temp->eh_) &&
+ ACE_BIT_DISABLED (temp->mask_, ~mask)) // the existing notificationmask
+ // is left with nothing when
+ // applying the mask
+ {
+ if (-1 == this->free_queue_.enqueue_head (temp))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_head")),
+ -1);
+ ++number_purged;
+ }
+ else
+ {
+ // To preserve it, move it to the local_queue.
+ // But first, if this is not a Reactor notify (it is for a particularhandler),
+ // and it matches the specified handler (or purging all), then
+ // apply the mask
+ if ((0 != temp->eh_) &&
+ (0 == eh || eh == temp->eh_))
+ ACE_CLR_BITS(temp->mask_, mask);
+ if (-1 == local_queue.enqueue_head (temp))
+ return -1;
+ }
+ }
+
+ if (this->notify_queue_.size ())
+ { // should be empty!
+ ACE_ASSERT (0);
+ return -1;
+ }
+
+ // now put it back in the notify queue
+ queue_size = local_queue.size ();
+ for (i = 0; i < queue_size; ++i)
+ {
+ if (-1 == local_queue.dequeue_head (temp))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("dequeue_head")),
+ -1);
+
+ if (-1 == this->notify_queue_.enqueue_head (temp))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_head")),
+ -1);
+ }
+
+ return number_purged;
+
+#else /* defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) */
+ ACE_UNUSED_ARG (eh);
+ ACE_UNUSED_ARG (mask);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) */
+}
+
+void
+ACE_Select_Reactor_Notify::dump (void) const
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("select_reactor_ = %x"), this->select_reactor_));
+ this->notification_pipe_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_Select_Reactor_Notify::open (ACE_Reactor_Impl *r,
+ ACE_Timer_Queue *,
+ int disable_notify_pipe)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::open");
+
+ if (disable_notify_pipe == 0)
+ {
+ this->select_reactor_ =
+ ACE_dynamic_cast (ACE_Select_Reactor_Impl *, r);
+
+ if (select_reactor_ == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (this->notification_pipe_.open () == -1)
+ return -1;
+#if defined (F_SETFD)
+ ACE_OS::fcntl (this->notification_pipe_.read_handle (), F_SETFD, 1);
+ ACE_OS::fcntl (this->notification_pipe_.write_handle (), F_SETFD, 1);
+#endif /* F_SETFD */
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ ACE_Notification_Buffer *temp;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Notification_Buffer[ACE_REACTOR_NOTIFICATION_ARRAY_SIZE],
+ -1);
+
+ if (this->alloc_queue_.enqueue_head (temp) == -1)
+ return -1;
+
+ for (size_t i = 0; i < ACE_REACTOR_NOTIFICATION_ARRAY_SIZE; i++)
+ if (free_queue_.enqueue_head (temp + i) == -1)
+ return -1;
+
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ // There seems to be a Win32 bug with this... Set this into
+ // non-blocking mode.
+ if (ACE::set_flags (this->notification_pipe_.read_handle (),
+ ACE_NONBLOCK) == -1)
+ return -1;
+ else
+ return this->select_reactor_->register_handler
+ (this->notification_pipe_.read_handle (),
+ this,
+ ACE_Event_Handler::READ_MASK);
+ }
+ else
+ {
+ this->select_reactor_ = 0;
+ return 0;
+ }
+}
+
+int
+ACE_Select_Reactor_Notify::close (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::close");
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ // Free up the dynamically allocated resources.
+ ACE_Notification_Buffer **b;
+
+ for (ACE_Unbounded_Queue_Iterator<ACE_Notification_Buffer *> alloc_iter (this->alloc_queue_);
+ alloc_iter.next (b) != 0;
+ alloc_iter.advance ())
+ {
+ delete [] *b;
+ *b = 0;
+ }
+
+ this->alloc_queue_.reset ();
+ this->notify_queue_.reset ();
+ this->free_queue_.reset ();
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ return this->notification_pipe_.close ();
+}
+
+ssize_t
+ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::notify");
+
+ // Just consider this method a "no-op" if there's no
+ // <ACE_Select_Reactor> configured.
+ if (this->select_reactor_ == 0)
+ return 0;
+ else
+ {
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ ACE_Notification_Buffer buffer (eh, mask);
+ // int notification_required = 0;
+
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ // No pending notifications.
+
+ // We will send notify for every message..
+ // if (this->notify_queue_.is_empty ())
+ // notification_required = 1;
+
+ ACE_Notification_Buffer *temp = 0;
+
+ if (free_queue_.dequeue_head (temp) == -1)
+ {
+ // Grow the queue of available buffers.
+ ACE_Notification_Buffer *temp1;
+
+ ACE_NEW_RETURN (temp1,
+ ACE_Notification_Buffer[ACE_REACTOR_NOTIFICATION_ARRAY_SIZE],
+ -1);
+
+ if (this->alloc_queue_.enqueue_head (temp1) == -1)
+ return -1;
+
+ // Start at 1 and enqueue only
+ // (ACE_REACTOR_NOTIFICATION_ARRAY_SIZE - 1) elements since
+ // the first one will be used right now.
+ for (size_t i = 1;
+ i < ACE_REACTOR_NOTIFICATION_ARRAY_SIZE;
+ i++)
+ this->free_queue_.enqueue_head (temp1 + i);
+
+ temp = temp1;
+ }
+
+ ACE_ASSERT (temp != 0);
+ *temp = buffer;
+
+ if (notify_queue_.enqueue_tail (temp) == -1)
+ return -1;
+
+ // Let us send a notify for every message
+ // if (notification_required)
+ {
+ ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
+ (char *) &buffer,
+ sizeof buffer,
+ timeout);
+ if (n == -1)
+ return -1;
+ }
+ return 0;
+#else
+ ACE_Notification_Buffer buffer (eh, mask);
+
+ ssize_t n = ACE::send (this->notification_pipe_.write_handle (),
+ (char *) &buffer,
+ sizeof buffer,
+ timeout);
+ if (n == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+ }
+}
+
+// Handles pending threads (if any) that are waiting to unblock the
+// Select_Reactor.
+
+int
+ACE_Select_Reactor_Notify::dispatch_notifications (int &number_of_active_handles,
+ ACE_Handle_Set &rd_mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::dispatch_notifications");
+
+ ACE_HANDLE read_handle =
+ this->notification_pipe_.read_handle ();
+
+ if (read_handle != ACE_INVALID_HANDLE
+ && rd_mask.is_set (read_handle))
+ {
+ number_of_active_handles--;
+ rd_mask.clr_bit (read_handle);
+ return this->handle_input (read_handle);
+ }
+ else
+ return 0;
+}
+
+
+ACE_HANDLE
+ACE_Select_Reactor_Notify::notify_handle (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::notify_handle");
+
+ return this->notification_pipe_.read_handle ();
+}
+
+
+// Special trick to unblock <select> when updates occur in somewhere
+// other than the main <ACE_Select_Reactor> thread. All we do is
+// write data to a pipe that the <ACE_Select_Reactor> is listening on.
+// Thanks to Paul Stephenson for suggesting this approach.
+int
+ACE_Select_Reactor_Notify::is_dispatchable (ACE_Notification_Buffer &buffer)
+{
+ // There is tonnes of code that can be abstracted...
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ ACE_Notification_Buffer *temp;
+
+ ACE_UNUSED_ARG (buffer);
+
+ // If the queue is empty just return 0
+ if (notify_queue_.is_empty ())
+ return 0;
+
+ if (this->notify_queue_.dequeue_head (temp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("dequeue_head")),
+ -1);
+ if (temp->eh_ != 0)
+ {
+ // If the queue had a buffer that has an event handler, put
+ // the element back in the queue and return a 1
+ if (this->notify_queue_.enqueue_head (temp) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enque_head")),
+ -1);
+ }
+
+ return 1;
+ }
+ // Else put the element in the free queue
+ if (free_queue_.enqueue_head (temp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_head")),
+ -1);
+ }
+#else
+ // If eh == 0 then another thread is unblocking the
+ // <ACE_Select_Reactor> to update the <ACE_Select_Reactor>'s
+ // internal structures. Otherwise, we need to dispatch the
+ // appropriate handle_* method on the <ACE_Event_Handler>
+ // pointer we've been passed.
+ if (buffer.eh_ != 0)
+ return 1;
+
+#endif /*ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ // has no dispatchable buffer
+ return 0;
+}
+
+int
+ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer)
+{
+ int result = 0;
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ // Dispatch all messages that are in the <notify_queue_>.
+ {
+ // We acquire the lock in a block to make sure we're not
+ // holding the lock while delivering callbacks...
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->notify_queue_lock_, -1);
+
+ ACE_Notification_Buffer *temp;
+
+ if (notify_queue_.is_empty ())
+ return 0;
+ else if (notify_queue_.dequeue_head (temp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("dequeue_head")),
+ -1);
+ buffer = *temp;
+ if (free_queue_.enqueue_head (temp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_head")),
+ -1);
+ }
+
+ // If eh == 0 then another thread is unblocking the
+ // <ACE_Select_Reactor> to update the <ACE_Select_Reactor>'s
+ // internal structures. Otherwise, we need to dispatch the
+ // appropriate handle_* method on the <ACE_Event_Handler>
+ // pointer we've been passed.
+ if (buffer.eh_ != 0)
+ {
+
+ switch (buffer.mask_)
+ {
+ case ACE_Event_Handler::READ_MASK:
+ case ACE_Event_Handler::ACCEPT_MASK:
+ result = buffer.eh_->handle_input (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::WRITE_MASK:
+ result = buffer.eh_->handle_output (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::EXCEPT_MASK:
+ result = buffer.eh_->handle_exception (ACE_INVALID_HANDLE);
+ break;
+ default:
+ // Should we bail out if we get an invalid mask?
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("invalid mask = %d\n"), buffer.mask_));
+ }
+ if (result == -1)
+ buffer.eh_->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::EXCEPT_MASK);
+ }
+#else
+ // If eh == 0 then another thread is unblocking the
+ // <ACE_Select_Reactor> to update the <ACE_Select_Reactor>'s
+ // internal structures. Otherwise, we need to dispatch the
+ // appropriate handle_* method on the <ACE_Event_Handler>
+ // pointer we've been passed.
+ if (buffer.eh_ != 0)
+ {
+ switch (buffer.mask_)
+ {
+ case ACE_Event_Handler::READ_MASK:
+ case ACE_Event_Handler::ACCEPT_MASK:
+ result = buffer.eh_->handle_input (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::WRITE_MASK:
+ result = buffer.eh_->handle_output (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::EXCEPT_MASK:
+ result = buffer.eh_->handle_exception (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::QOS_MASK:
+ result = buffer.eh_->handle_qos (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::GROUP_QOS_MASK:
+ result = buffer.eh_->handle_group_qos (ACE_INVALID_HANDLE);
+ break;
+ default:
+ // Should we bail out if we get an invalid mask?
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("invalid mask = %d\n"),
+ buffer.mask_));
+ }
+ if (result == -1)
+ buffer.eh_->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::EXCEPT_MASK);
+ }
+
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+ return 1;
+}
+
+int
+ACE_Select_Reactor_Notify::read_notify_pipe (ACE_HANDLE handle,
+ ACE_Notification_Buffer &buffer)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::read_notify_pipe");
+
+ ssize_t n = ACE::recv (handle, (char *) &buffer, sizeof buffer);
+
+ if (n > 0)
+ {
+ // Check to see if we've got a short read.
+ if (n != sizeof buffer)
+ {
+ ssize_t remainder = sizeof buffer - n;
+
+ // If so, try to recover by reading the remainder. If this
+ // doesn't work we're in big trouble since the input stream
+ // won't be aligned correctly. I'm not sure quite what to
+ // do at this point. It's probably best just to return -1.
+ if (ACE::recv (handle,
+ ((char *) &buffer) + n,
+ remainder) != remainder)
+ return -1;
+ }
+
+
+ return 1;
+ }
+
+ // Return -1 if things have gone seriously wrong.
+ if (n <= 0 && (errno != EWOULDBLOCK && errno != EAGAIN))
+ return -1;
+
+ return 0;
+}
+
+
+int
+ACE_Select_Reactor_Notify::handle_input (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Notify::handle_input");
+ // Precondition: this->select_reactor_.token_.current_owner () ==
+ // ACE_Thread::self ();
+
+ int number_dispatched = 0;
+ int result = 0;
+ ACE_Notification_Buffer buffer;
+
+ while ((result = this->read_notify_pipe (handle, buffer)) > 0)
+ {
+ // Dispatch the buffer
+ // NOTE: We count only if we made any dispatches ie. upcalls.
+ if (this->dispatch_notify (buffer) > 0)
+ number_dispatched++;
+
+ // Bail out if we've reached the <notify_threshold_>. Note that
+ // by default <notify_threshold_> is -1, so we'll loop until all
+ // the notifications in the pipe have been dispatched.
+ if (number_dispatched == this->max_notify_iterations_)
+ break;
+ }
+
+ // Reassign number_dispatched to -1 if things have gone seriously
+ // wrong.
+ if (result < 0)
+ number_dispatched = -1;
+
+ // Enqueue ourselves into the list of waiting threads. When we
+ // reacquire the token we'll be off and running again with ownership
+ // of the token. The postcondition of this call is that
+ // <select_reactor_.token_.current_owner> == <ACE_Thread::self>.
+ this->select_reactor_->renew ();
+ return number_dispatched;
+}
+
+// Perform GET, CLR, SET, and ADD operations on the Handle_Sets.
+//
+// GET = 1, Retrieve current value
+// SET = 2, Set value of bits to new mask (changes the entire mask)
+// ADD = 3, Bitwise "or" the value into the mask (only changes
+// enabled bits)
+// CLR = 4 Bitwise "and" the negation of the value out of the mask
+// (only changes enabled bits)
+//
+// Returns the original mask. Must be called with locks held.
+
+int
+ACE_Select_Reactor_Impl::bit_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Select_Reactor_Handle_Set &handle_set,
+ int ops)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Impl::bit_ops");
+ if (this->handler_rep_.handle_in_range (handle) == 0)
+ return -1;
+
+#if !defined (ACE_WIN32)
+ ACE_Sig_Guard sb; // Block out all signals until method returns.
+#endif /* ACE_WIN32 */
+
+ ACE_FDS_PTMF ptmf = &ACE_Handle_Set::set_bit;
+ u_long omask = ACE_Event_Handler::NULL_MASK;
+
+ // Find the old reactor masks. This automatically does the work of
+ // the GET_MASK operation.
+ if (handle_set.rd_mask_.is_set (handle))
+ ACE_SET_BITS (omask, ACE_Event_Handler::READ_MASK);
+ if (handle_set.wr_mask_.is_set (handle))
+ ACE_SET_BITS (omask, ACE_Event_Handler::WRITE_MASK);
+ if (handle_set.ex_mask_.is_set (handle))
+ ACE_SET_BITS (omask, ACE_Event_Handler::EXCEPT_MASK);
+
+ switch (ops)
+ {
+ case ACE_Reactor::GET_MASK:
+ // The work for this operation is done in all cases at the
+ // begining of the function.
+ break;
+ case ACE_Reactor::CLR_MASK:
+ ptmf = &ACE_Handle_Set::clr_bit;
+ /* FALLTHRU */
+ case ACE_Reactor::SET_MASK:
+ /* FALLTHRU */
+ case ACE_Reactor::ADD_MASK:
+
+ // The following code is rather subtle... Note that if we are
+ // doing a ACE_Reactor::SET_MASK then if the bit is not enabled
+ // in the mask we need to clear the bit from the ACE_Handle_Set.
+ // On the other hand, if we are doing a ACE_Reactor::CLR_MASK or
+ // a ACE_Reactor::ADD_MASK we just carry out the operations
+ // specified by the mask.
+
+ // READ, ACCEPT, and CONNECT flag will place the handle in the
+ // read set.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK)
+ || ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK)
+ || ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK))
+ {
+ (handle_set.rd_mask_.*ptmf) (handle);
+ }
+ else if (ops == ACE_Reactor::SET_MASK)
+ handle_set.rd_mask_.clr_bit (handle);
+
+ // WRITE and CONNECT flag will place the handle in the write set
+ if (ACE_BIT_ENABLED (mask,
+ ACE_Event_Handler::WRITE_MASK)
+ || ACE_BIT_ENABLED (mask,
+ ACE_Event_Handler::CONNECT_MASK))
+ {
+ (handle_set.wr_mask_.*ptmf) (handle);
+ }
+ else if (ops == ACE_Reactor::SET_MASK)
+ handle_set.wr_mask_.clr_bit (handle);
+
+ // EXCEPT (and CONNECT on Win32) flag will place the handle in
+ // the except set.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK)
+#if defined (ACE_WIN32)
+ || ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)
+#endif /* ACE_WIN32 */
+ )
+ {
+ (handle_set.ex_mask_.*ptmf) (handle);
+ }
+ else if (ops == ACE_Reactor::SET_MASK)
+ handle_set.ex_mask_.clr_bit (handle);
+ break;
+ default:
+ return -1;
+ }
+ return omask;
+}
+
+int
+ACE_Select_Reactor_Impl::resumable_handler (void)
+{
+ // The select reactor has no handlers that can be resumed by the
+ // application. So return 0;
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+template class ACE_Unbounded_Queue <ACE_Notification_Buffer *>;
+template class ACE_Unbounded_Queue_Iterator <ACE_Notification_Buffer *>;
+template class ACE_Node <ACE_Notification_Buffer *>;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+#pragma instantiate ACE_Unbounded_Queue <ACE_Notification_Buffer *>
+#pragma instantiate ACE_Unbounded_Queue_Iterator <ACE_Notification_Buffer *>
+#pragma instantiate ACE_Node <ACE_Notification_Buffer *>
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Demux/Select_Reactor_Base.h b/ace/Demux/Select_Reactor_Base.h
new file mode 100644
index 00000000000..62c2bec4f50
--- /dev/null
+++ b/ace/Demux/Select_Reactor_Base.h
@@ -0,0 +1,537 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Select_Reactor_Base.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SELECT_REACTOR_BASE_H
+#define ACE_SELECT_REACTOR_BASE_H
+#include "ace/pre.h"
+
+#include "ace/Signal.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Queue.h"
+#include "ace/Event_Handler.h"
+#include "ace/Handle_Set.h"
+#include "ace/Token.h"
+#include "ace/Pipe.h"
+#include "ace/Reactor_Impl.h"
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+#include "ace/Unbounded_Queue.h"
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+
+// Add useful typedefs to simplify the following code.
+typedef void (ACE_Handle_Set::*ACE_FDS_PTMF) (ACE_HANDLE);
+typedef int (ACE_Event_Handler::*ACE_EH_PTMF) (ACE_HANDLE);
+
+// Forward declaration.
+class ACE_Select_Reactor_Impl;
+
+/**
+ * @class ACE_Select_Reactor_Handle_Set
+ *
+ * @brief Track handles we are interested for various events.
+ */
+class ACE_Export ACE_Select_Reactor_Handle_Set
+{
+public:
+ /// Read events (e.g., input pending, accept pending).
+ ACE_Handle_Set rd_mask_;
+
+ /// Write events (e.g., flow control abated, non-blocking connection
+ /// complete).
+ ACE_Handle_Set wr_mask_;
+
+ /// Exception events (e.g., SIG_URG).
+ ACE_Handle_Set ex_mask_;
+};
+
+/**
+ * @class ACE_Event_Tuple
+ *
+ * @brief An ACE_Event_Handler and its associated ACE_HANDLE.
+ *
+ * One <ACE_Event_Handler> is registered for one or more
+ * <ACE_HANDLE>. At various points, this information must be
+ * stored explicitly. This class provides a lightweight
+ * mechanism to do so.
+ */
+class ACE_Export ACE_Event_Tuple
+{
+public:
+ /// Default constructor.
+ ACE_Event_Tuple (void);
+
+ /// Constructor.
+ ACE_Event_Tuple (ACE_Event_Handler *eh,
+ ACE_HANDLE h);
+
+ /// Destructor.
+ ~ACE_Event_Tuple (void);
+
+ /// Equality operator.
+ int operator== (const ACE_Event_Tuple &rhs) const;
+
+ /// Inequality operator.
+ int operator!= (const ACE_Event_Tuple &rhs) const;
+
+ /// Handle.
+ ACE_HANDLE handle_;
+
+ /// <ACE_Event_Handler> associated with the <ACE_HANDLE>.
+ ACE_Event_Handler *event_handler_;
+};
+
+/**
+ * @class ACE_Select_Reactor_Notify
+ *
+ * @brief Unblock the <ACE_Select_Reactor> from its event loop.
+ *
+ * This implementation is necessary for cases where the
+ * <ACE_Select_Reactor> is run in a multi-threaded program. In
+ * this case, we need to be able to unblock <select> or <poll>
+ * when updates occur other than in the main
+ * <ACE_Select_Reactor> thread. To do this, we signal an
+ * auto-reset event the <ACE_Select_Reactor> is listening on.
+ * If an <ACE_Event_Handler> and <ACE_Select_Reactor_Mask> is
+ * passed to <notify>, the appropriate <handle_*> method is
+ * dispatched in the context of the <ACE_Select_Reactor> thread.
+ */
+class ACE_Export ACE_Select_Reactor_Notify : public ACE_Reactor_Notify
+{
+public:
+ /// Default dtor.
+ ACE_Select_Reactor_Notify (void);
+ ~ACE_Select_Reactor_Notify (void);
+
+ // = Initialization and termination methods.
+ /// Initialize.
+ virtual int open (ACE_Reactor_Impl *,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0);
+
+ /// Destroy.
+ virtual int close (void);
+
+ /**
+ * Called by a thread when it wants to unblock the
+ * <ACE_Select_Reactor>. This wakeups the <ACE_Select_Reactor> if
+ * currently blocked in <select>/<poll>. Pass over both the
+ * <Event_Handler> *and* the <mask> to allow the caller to dictate
+ * which <Event_Handler> method the <ACE_Select_Reactor> will
+ * invoke. The <ACE_Time_Value> indicates how long to blocking
+ * trying to notify the <ACE_Select_Reactor>. If <timeout> == 0,
+ * the caller will block until action is possible, else will wait
+ * until the relative time specified in *<timeout> elapses).
+ */
+ virtual ssize_t notify (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 0);
+
+ /// Handles pending threads (if any) that are waiting to unblock the
+ /// <ACE_Select_Reactor>.
+ virtual int dispatch_notifications (int &number_of_active_handles,
+ ACE_Handle_Set &rd_mask);
+
+ /// Returns the ACE_HANDLE of the notify pipe on which the reactor
+ /// is listening for notifications so that other threads can unblock
+ /// the Select_Reactor
+ virtual ACE_HANDLE notify_handle (void);
+
+ /// Handle one of the notify call on the <handle>. This could be
+ /// because of a thread trying to unblock the <Reactor_Impl>
+ virtual int dispatch_notify (ACE_Notification_Buffer &buffer);
+
+ /// Read one of the notify call on the <handle> into the
+ /// <buffer>. This could be because of a thread trying to unblock
+ /// the <Reactor_Impl>
+ virtual int read_notify_pipe (ACE_HANDLE handle,
+ ACE_Notification_Buffer &buffer);
+
+ /// Verify whether the buffer has dispatchable info or not.
+ virtual int is_dispatchable (ACE_Notification_Buffer &buffer);
+
+ /// Called back by the <ACE_Select_Reactor> when a thread wants to
+ /// unblock us.
+ virtual int handle_input (ACE_HANDLE handle);
+
+ /**
+ * Set the maximum number of times that the
+ * <ACE_Select_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify pipe before breaking out of its <recv> loop. By default,
+ * this is set to -1, which means "iterate until the pipe is empty."
+ * Setting this to a value like "1 or 2" will increase "fairness"
+ * (and thus prevent starvation) at the expense of slightly higher
+ * dispatching overhead.
+ */
+ virtual void max_notify_iterations (int);
+
+ /**
+ * Get the maximum number of times that the
+ * <ACE_Select_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify pipe before breaking out of its <recv> loop.
+ */
+ virtual int max_notify_iterations (void);
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. If <eh> == 0, all notifications for all
+ * handlers are removed (but not any notifications posted just to wake up
+ * the reactor itself). Returns the number of notifications purged.
+ * Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler *,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /**
+ * Keep a back pointer to the <ACE_Select_Reactor>. If this value
+ * if NULL then the <ACE_Select_Reactor> has been initialized with
+ * <disable_notify_pipe>.
+ */
+ ACE_Select_Reactor_Impl *select_reactor_;
+
+ /**
+ * Contains the <ACE_HANDLE> the <ACE_Select_Reactor> is listening
+ * on, as well as the <ACE_HANDLE> that threads wanting the
+ * attention of the <ACE_Select_Reactor> will write to.
+ */
+ ACE_Pipe notification_pipe_;
+
+ /**
+ * Keeps track of the maximum number of times that the
+ * <ACE_Select_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify pipe before breaking out of its <recv> loop. By default,
+ * this is set to -1, which means "iterate until the pipe is empty."
+ */
+ int max_notify_iterations_;
+
+#if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
+ // = This configuration queues up notifications in separate buffers that
+ // are in user-space, rather than stored in a pipe in the OS
+ // kernel. The kernel-level notifications are used only to trigger
+ // the Reactor to check its notification queue. This enables many
+ // more notifications to be stored than would otherwise be the case.
+
+ /// Keeps track of allocated arrays of type
+ /// <ACE_Notification_Buffer>.
+ ACE_Unbounded_Queue <ACE_Notification_Buffer *> alloc_queue_;
+
+ /// Keeps track of all pending notifications.
+ ACE_Unbounded_Queue <ACE_Notification_Buffer *> notify_queue_;
+
+ /// Keeps track of all free buffers.
+ ACE_Unbounded_Queue <ACE_Notification_Buffer *> free_queue_;
+
+ /// Synchronization for handling of queues.
+ ACE_SYNCH_MUTEX notify_queue_lock_;
+#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
+};
+
+/**
+ * @class ACE_Select_Reactor_Handler_Repository
+ *
+ * @brief Used to map <ACE_HANDLE>s onto the appropriate
+ * <ACE_Event_Handler> *.
+ *
+ * This class is necessary to shield differences between UNIX
+ * and Win32. In UNIX, <ACE_HANDLE> is an int, whereas in Win32
+ * it's a void *. This class hides all these details from the
+ * bulk of the <ACE_Select_Reactor> code. All of these methods
+ * are called with the main <Select_Reactor> token lock held.
+ */
+class ACE_Export ACE_Select_Reactor_Handler_Repository
+{
+public:
+ friend class ACE_Select_Reactor_Handler_Repository_Iterator;
+
+ // = Initialization and termination methods.
+ /// Default "do-nothing" constructor.
+ ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl &);
+
+ /// dtor.
+ ~ACE_Select_Reactor_Handler_Repository (void);
+
+ /// Initialize a repository of the appropriate <size>.
+ /**
+ * On Unix platforms, the size parameter should be as large as the
+ * maximum number of file descriptors allowed for a given process.
+ * This is necessary since a file descriptor is used to directly
+ * index the array of event handlers maintained by the Reactor's
+ * handler repository. Direct indexing is used for efficiency
+ * reasons.
+ */
+ int open (size_t size);
+
+ /// Close down the repository.
+ int close (void);
+
+ // = Search structure operations.
+
+ /**
+ * Return the <ACE_Event_Handler *> associated with <ACE_HANDLE>.
+ * If <index_p> is non-0, then return the index location of the
+ * <handle>, if found.
+ */
+ ACE_Event_Handler *find (ACE_HANDLE handle, size_t *index_p = 0);
+
+ /// Bind the <ACE_Event_Handler *> to the <ACE_HANDLE> with the
+ /// appropriate <ACE_Reactor_Mask> settings.
+ int bind (ACE_HANDLE,
+ ACE_Event_Handler *,
+ ACE_Reactor_Mask);
+
+ /// Remove the binding of <ACE_HANDLE> in accordance with the <mask>.
+ int unbind (ACE_HANDLE,
+ ACE_Reactor_Mask mask);
+
+ /// Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples.
+ int unbind_all (void);
+
+ // = Sanity checking.
+
+ // Check the <handle> to make sure it's a valid ACE_HANDLE that
+ // within the range of legal handles (i.e., >= 0 && < max_size_).
+ int invalid_handle (ACE_HANDLE handle);
+
+ // Check the <handle> to make sure it's a valid ACE_HANDLE that
+ // within the range of currently registered handles (i.e., >= 0 && <
+ // max_handlep1_).
+ int handle_in_range (ACE_HANDLE handle);
+
+ // = Accessors.
+ /// Returns the current table size.
+ size_t size (void) const;
+
+ /// Maximum ACE_HANDLE value, plus 1.
+ size_t max_handlep1 (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Reference to our <Select_Reactor>.
+ ACE_Select_Reactor_Impl &select_reactor_;
+
+ /// Maximum number of handles.
+ ssize_t max_size_;
+
+ /// The highest currently active handle, plus 1 (ranges between 0 and
+ /// <max_size_>.
+ int max_handlep1_;
+
+#if defined (ACE_WIN32)
+ // = The mapping from <HANDLES> to <Event_Handlers>.
+
+ /**
+ * The NT version implements this via a dynamically allocated
+ * array of <ACE_Event_Tuple *>. Since NT implements ACE_HANDLE
+ * as a void * we can't directly index into this array. Therefore,
+ * we just do a linear search (for now). Next, we'll modify
+ * things to use hashing or something faster...
+ */
+ ACE_Event_Tuple *event_handlers_;
+#else
+ /**
+ * The UNIX version implements this via a dynamically allocated
+ * array of <ACE_Event_Handler *> that is indexed directly using
+ * the ACE_HANDLE value.
+ */
+ ACE_Event_Handler **event_handlers_;
+#endif /* ACE_WIN32 */
+};
+
+/**
+ * @class ACE_Select_Reactor_Handler_Repository_Iterator
+ *
+ * @brief Iterate through the <ACE_Select_Reactor_Handler_Repository>.
+ */
+class ACE_Export ACE_Select_Reactor_Handler_Repository_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Select_Reactor_Handler_Repository_Iterator (const ACE_Select_Reactor_Handler_Repository *s);
+
+ /// dtor.
+ ~ACE_Select_Reactor_Handler_Repository_Iterator (void);
+
+ // = Iteration methods.
+
+ /// Pass back the <next_item> that hasn't been seen in the Set.
+ /// Returns 0 when all items have been seen, else 1.
+ int next (ACE_Event_Handler *&next_item);
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Move forward by one element in the set. Returns 0 when all the
+ /// items in the set have been seen, else 1.
+ int advance (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Reference to the Handler_Repository we are iterating over.
+ const ACE_Select_Reactor_Handler_Repository *rep_;
+
+ /// Pointer to the current iteration level.
+ ssize_t current_;
+};
+
+/**
+ * @class ACE_Select_Reactor_Impl
+ *
+ * @brief This class simply defines how Select_Reactor's basic interface
+ * functions should look like and provides a common base class for
+ * <Select_Reactor> using various locking mechanism.
+ */
+class ACE_Export ACE_Select_Reactor_Impl : public ACE_Reactor_Impl
+{
+public:
+ enum
+ {
+ /// Default size of the Select_Reactor's handle table.
+ DEFAULT_SIZE = ACE_DEFAULT_SELECT_REACTOR_SIZE
+ };
+
+ /// Constructor.
+ ACE_Select_Reactor_Impl (void);
+
+ friend class ACE_Select_Reactor_Notify;
+ friend class ACE_Select_Reactor_Handler_Repository;
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. Returns the number of notifications
+ * purged. Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Does the reactor allow the application to resume the handle on
+ /// its own ie. can it pass on the control of handle resumption to
+ /// the application. The select reactor has no handlers that can be
+ /// resumed by the application. So return 0;
+ virtual int resumable_handler (void);
+
+protected:
+ /// Allow manipulation of the <wait_set_> mask and <ready_set_> mask.
+ virtual int bit_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Select_Reactor_Handle_Set &wait_Set,
+ int ops);
+
+ /// Enqueue ourselves into the list of waiting threads at the
+ /// appropriate point specified by <requeue_position_>.
+ virtual void renew (void) = 0;
+
+ /// Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s.
+ ACE_Select_Reactor_Handler_Repository handler_rep_;
+
+ /// Tracks handles that are waited for by <select>.
+ ACE_Select_Reactor_Handle_Set wait_set_;
+
+ /// Tracks handles that are currently suspended.
+ ACE_Select_Reactor_Handle_Set suspend_set_;
+
+ /// Track HANDLES we are interested in for various events that must
+ /// be dispatched *without* going through <select>.
+ ACE_Select_Reactor_Handle_Set ready_set_;
+
+ /// Defined as a pointer to allow overriding by derived classes...
+ ACE_Timer_Queue *timer_queue_;
+
+ /// Keeps track of whether we should delete the timer queue (if we
+ /// didn't create it, then we don't delete it).
+ int delete_timer_queue_;
+
+ /// Handle signals without requiring global/static variables.
+ ACE_Sig_Handler *signal_handler_;
+
+ /// Keeps track of whether we should delete the signal handler (if we
+ /// didn't create it, then we don't delete it).
+ int delete_signal_handler_;
+
+ /// Callback object that unblocks the <ACE_Select_Reactor> if it's
+ /// sleeping.
+ ACE_Reactor_Notify *notify_handler_;
+
+ /// Keeps track of whether we need to delete the notify handler (if
+ /// we didn't create it, then we don't delete it).
+ int delete_notify_handler_;
+
+ /// Restart the <handle_events> event-loop method automatically when
+ /// <select> is interrupted via <EINTR>.
+ int restart_;
+
+ /**
+ * Position that the main ACE_Select_Reactor thread is requeued in
+ * the list of waiters during a <notify> callback. If this value ==
+ * -1 we are requeued at the end of the list. Else if it's 0 then
+ * we are requeued at the front of the list. Else if it's > 1 then
+ * that indicates the number of waiters to skip over.
+ */
+ int requeue_position_;
+
+ /// True if we've been initialized yet...
+ int initialized_;
+
+ /// The original thread that created this Select_Reactor.
+ ACE_thread_t owner_;
+
+ /**
+ * True if state has changed during dispatching of
+ * <ACE_Event_Handlers>, else false. This is used to determine
+ * whether we need to make another trip through the
+ * <Select_Reactor>'s <wait_for_multiple_events> loop.
+ */
+ int state_changed_;
+
+ /// Controls/access whether the notify handler should renew the
+ /// Select_Reactor's token or not.
+ int supress_notify_renew (void);
+ void supress_notify_renew (int sr);
+
+private:
+ /// Determine whether we should renew Select_Reactor's token after handling
+ /// the notification message.
+ int supress_renew_;
+
+ /// Deny access since member-wise won't work...
+ ACE_Select_Reactor_Impl (const ACE_Select_Reactor_Impl &);
+ ACE_Select_Reactor_Impl &operator = (const ACE_Select_Reactor_Impl &);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_Base.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SELECT_REACTOR_BASE_H */
diff --git a/ace/Demux/Select_Reactor_Base.i b/ace/Demux/Select_Reactor_Base.i
new file mode 100644
index 00000000000..f04446e2e86
--- /dev/null
+++ b/ace/Demux/Select_Reactor_Base.i
@@ -0,0 +1,93 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Reactor.h"
+
+ACE_INLINE
+ACE_Event_Tuple::~ACE_Event_Tuple (void)
+{
+}
+
+ACE_INLINE
+ACE_Select_Reactor_Notify::~ACE_Select_Reactor_Notify (void)
+{
+}
+
+ACE_INLINE
+ACE_Select_Reactor_Handler_Repository::~ACE_Select_Reactor_Handler_Repository (void)
+{
+}
+
+ACE_INLINE
+ACE_Select_Reactor_Handler_Repository_Iterator::~ACE_Select_Reactor_Handler_Repository_Iterator (void)
+{
+}
+
+ACE_INLINE size_t
+ACE_Select_Reactor_Handler_Repository::size (void) const
+{
+ return this->max_size_;
+}
+
+ACE_INLINE
+ACE_Event_Tuple::ACE_Event_Tuple (void)
+: handle_ (ACE_INVALID_HANDLE),
+ event_handler_ (0)
+{
+}
+
+ACE_INLINE
+ACE_Event_Tuple::ACE_Event_Tuple (ACE_Event_Handler* eh,
+ ACE_HANDLE h)
+: handle_ (h),
+ event_handler_ (eh)
+{
+}
+
+ACE_INLINE int
+ACE_Event_Tuple::operator== (const ACE_Event_Tuple &rhs) const
+{
+ return this->handle_ == rhs.handle_;
+}
+
+ACE_INLINE int
+ACE_Event_Tuple::operator!= (const ACE_Event_Tuple &rhs) const
+{
+ return !(*this == rhs);
+}
+
+ACE_INLINE
+ACE_Select_Reactor_Impl::ACE_Select_Reactor_Impl ()
+ : handler_rep_ (*this),
+ timer_queue_ (0),
+ delete_timer_queue_ (0),
+ delete_signal_handler_ (0),
+ delete_notify_handler_ (0),
+ requeue_position_ (-1), // Requeue at end of waiters by default.
+ initialized_ (0),
+ state_changed_ (0),
+ supress_renew_ (0)
+{
+}
+
+ACE_INLINE int
+ACE_Select_Reactor_Impl::purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ if (this->notify_handler_ == 0)
+ return 0;
+ else
+ return this->notify_handler_->purge_pending_notifications (eh, mask);
+}
+
+ACE_INLINE int
+ACE_Select_Reactor_Impl::supress_notify_renew (void)
+{
+ return this->supress_renew_;
+}
+
+ACE_INLINE void
+ACE_Select_Reactor_Impl::supress_notify_renew (int sr)
+{
+ this->supress_renew_ = sr;
+}
diff --git a/ace/Demux/Select_Reactor_T.cpp b/ace/Demux/Select_Reactor_T.cpp
new file mode 100644
index 00000000000..030397747b4
--- /dev/null
+++ b/ace/Demux/Select_Reactor_T.cpp
@@ -0,0 +1,1427 @@
+// $Id$
+
+#ifndef ACE_SELECT_REACTOR_T_C
+#define ACE_SELECT_REACTOR_T_C
+
+#include "ace/Select_Reactor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Log_Msg.h"
+#include "ace/Thread.h"
+#include "ace/Timer_Heap.h"
+
+// @@ The latest version of SunCC can't grok the code if we put inline
+// function here. Therefore, we temporarily disable the code here.
+// We shall turn this back on once we know the problem gets fixed.
+#if 1 // !defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_T.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Select_Reactor_T, "$Id$")
+
+ ACE_ALLOC_HOOK_DEFINE(ACE_Select_Reactor_T)
+
+#if defined (ACE_WIN32)
+#define ACE_SELECT_REACTOR_HANDLE(H) (this->event_handlers_[(H)].handle_)
+#define ACE_SELECT_REACTOR_EVENT_HANDLER(THIS,H) ((THIS)->event_handlers_[(H)].event_handler_)
+#else
+#define ACE_SELECT_REACTOR_HANDLE(H) (H)
+#define ACE_SELECT_REACTOR_EVENT_HANDLER(THIS,H) ((THIS)->event_handlers_[(H)])
+#endif /* ACE_WIN32 */
+
+ template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready
+ (ACE_Select_Reactor_Handle_Set &wait_set)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::any_ready");
+
+ if (this->mask_signals_)
+ {
+#if !defined (ACE_WIN32)
+ // Make this call signal safe.
+ ACE_Sig_Guard sb;
+#endif /* ACE_WIN32 */
+
+ return this->any_ready_i (wait_set);
+ }
+ return this->any_ready_i (wait_set);
+}
+
+ template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready_i
+ (ACE_Select_Reactor_Handle_Set &wait_set)
+{
+ int number_ready = this->ready_set_.rd_mask_.num_set ()
+ + this->ready_set_.wr_mask_.num_set ()
+ + this->ready_set_.ex_mask_.num_set ();
+
+ if (number_ready > 0 && &wait_set != &(this->ready_set_))
+ {
+ wait_set.rd_mask_ = this->ready_set_.rd_mask_;
+ wait_set.wr_mask_ = this->ready_set_.wr_mask_;
+ wait_set.ex_mask_ = this->ready_set_.ex_mask_;
+
+ this->ready_set_.rd_mask_.reset ();
+ this->ready_set_.wr_mask_.reset ();
+ this->ready_set_.ex_mask_.reset ();
+ }
+
+ return number_ready;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i (int signum,
+ ACE_Event_Handler **eh)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handler_i");
+ ACE_Event_Handler *handler = this->signal_handler_->handler (signum);
+
+ if (handler == 0)
+ return -1;
+ else if (eh != 0 && *eh != 0)
+ *eh = handler;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::initialized (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::initialized");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, 0));
+ return this->initialized_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::owner (ACE_thread_t tid,
+ ACE_thread_t *o_id)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::owner");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ if (o_id)
+ *o_id = this->owner_;
+
+ this->owner_ = tid;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::owner (ACE_thread_t *t_id)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::owner");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ *t_id = this->owner_;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::restart (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->restart_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::restart (int r)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ int current_value = this->restart_;
+ this->restart_ = r;
+ return current_value;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::requeue_position (int rp)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::requeue_position");
+ ACE_MT (ACE_GUARD (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_));
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (rp);
+ // Must always requeue ourselves "next" on Win32.
+ this->requeue_position_ = 0;
+#else
+ this->requeue_position_ = rp;
+#endif /* ACE_WIN32 */
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::requeue_position (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::requeue_position");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->requeue_position_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::max_notify_iterations (int iterations)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::max_notify_iterations");
+ ACE_MT (ACE_GUARD (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_));
+
+ this->notify_handler_->max_notify_iterations (iterations);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::max_notify_iterations (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::max_notify_iterations");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->notify_handler_->max_notify_iterations ();
+}
+
+// Enqueue ourselves into the list of waiting threads.
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::renew (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::renew");
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ if (this->supress_notify_renew () == 0)
+ this->token_.renew (this->requeue_position_);
+#endif /* defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) */
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX> void
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::dump (void) const
+{
+ ACE_TRACE ("ACE_Select_Reactor_Token_T::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX>
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::ACE_Select_Reactor_Token_T
+ (ACE_Select_Reactor_Impl &r)
+ : select_reactor_ (&r)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Token_T::ACE_Select_Reactor_Token");
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX>
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::ACE_Select_Reactor_Token_T (void)
+ : select_reactor_ (0)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Token_T::ACE_Select_Reactor_Token");
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX>
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::~ACE_Select_Reactor_Token_T (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Token_T::~ACE_Select_Reactor_Token_T");
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX> ACE_Select_Reactor_Impl &
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::select_reactor (void)
+{
+ return *this->select_reactor_;
+}
+
+template <class ACE_SELECT_REACTOR_MUTEX> void
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::select_reactor
+ (ACE_Select_Reactor_Impl &select_reactor)
+{
+ this->select_reactor_ = &select_reactor;
+}
+
+// Used to wakeup the Select_Reactor.
+
+template <class ACE_SELECT_REACTOR_MUTEX> void
+ACE_Select_Reactor_Token_T<ACE_SELECT_REACTOR_MUTEX>::sleep_hook (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_Token_T::sleep_hook");
+ if (this->select_reactor_->notify () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("sleep_hook failed")));
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::notify");
+
+ ssize_t n = 0;
+
+ // Pass over both the Event_Handler *and* the mask to allow the
+ // caller to dictate which Event_Handler method the receiver
+ // invokes. Note that this call can timeout.
+
+ n = this->notify_handler_->notify (eh, mask, timeout);
+ return n == -1 ? -1 : 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handler (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::resume_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->resume_i (handle);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handler (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::suspend_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->suspend_i (handle);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handlers (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::suspend_handlers");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ ACE_Event_Handler *eh = 0;
+
+ for (ACE_Select_Reactor_Handler_Repository_Iterator iter (&this->handler_rep_);
+ iter.next (eh) != 0;
+ iter.advance ())
+ this->suspend_i (eh->get_handle ());
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handlers (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::resume_handlers");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ ACE_Event_Handler *eh = 0;
+
+ for (ACE_Select_Reactor_Handler_Repository_Iterator iter (&this->handler_rep_);
+ iter.next (eh) != 0;
+ iter.advance ())
+ this->resume_i (eh->get_handle ());
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
+ (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->register_handler_i (handler->get_handle (), handler, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
+ (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->register_handler_i (handle, handler, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
+ (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->register_handler_i (handles, handler, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **handler)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->handler_i (handle, mask, handler);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
+ (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->remove_handler_i (handles, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
+ (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->remove_handler_i (handler->get_handle (), mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->remove_handler_i (handle, mask);
+}
+
+// Performs operations on the "ready" bits.
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ready_ops
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ready_ops");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->bit_ops (handle,
+ mask,
+ this->ready_set_,
+ ops);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::open
+ (size_t size,
+ int restart,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::open");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ // Can't initialize ourselves more than once.
+ if (this->initialized_ > 0)
+ return -1;
+
+ this->owner_ = ACE_Thread::self ();
+ this->restart_ = restart;
+ this->signal_handler_ = sh;
+ this->timer_queue_ = tq;
+ this->notify_handler_ = notify;
+
+ int result = 0;
+
+ // Allows the signal handler to be overridden.
+ if (this->signal_handler_ == 0)
+ {
+ ACE_NEW_RETURN (this->signal_handler_,
+ ACE_Sig_Handler,
+ -1);
+
+ if (this->signal_handler_ == 0)
+ result = -1;
+ else
+ this->delete_signal_handler_ = 1;
+ }
+
+ // Allows the timer queue to be overridden.
+ if (result != -1 && this->timer_queue_ == 0)
+ {
+ ACE_NEW_RETURN (this->timer_queue_,
+ ACE_Timer_Heap,
+ -1);
+
+ if (this->timer_queue_ == 0)
+ result = -1;
+ else
+ this->delete_timer_queue_ = 1;
+ }
+
+ // Allows the Notify_Handler to be overridden.
+ if (result != -1 && this->notify_handler_ == 0)
+ {
+ ACE_NEW_RETURN (this->notify_handler_,
+ ACE_Select_Reactor_Notify,
+ -1);
+
+ if (this->notify_handler_ == 0)
+ result = -1;
+ else
+ this->delete_notify_handler_ = 1;
+ }
+
+ if (result != -1 && this->handler_rep_.open (size) == -1)
+ result = -1;
+ else if (this->notify_handler_->open (this,
+ 0,
+ disable_notify_pipe) == -1)
+ result = -1;
+
+ if (result != -1)
+ // We're all set to go.
+ this->initialized_ = 1;
+ else
+ // This will close down all the allocated resources properly.
+ this->close ();
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::set_sig_handler
+ (ACE_Sig_Handler *signal_handler)
+{
+ if (this->signal_handler_ != 0 && this->delete_signal_handler_ != 0)
+ delete this->signal_handler_;
+ this->signal_handler_ = signal_handler;
+ this->delete_signal_handler_ = 0;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> ACE_Timer_Queue *
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::timer_queue
+ (ACE_Timer_Queue *tq)
+{
+ if (this->timer_queue_ != 0 && this->delete_timer_queue_ != 0)
+ delete this->timer_queue_;
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = 0;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::set_timer_queue
+ (ACE_Timer_Queue *tq)
+{
+ return this->timer_queue (tq);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN>
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ACE_Select_Reactor_T
+ (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals)
+ : token_ (*this),
+ lock_adapter_ (token_),
+ deactivated_ (0),
+ mask_signals_ (mask_signals)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
+
+ // First try to open the Reactor with the hard-coded default.
+ if (this->open (ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::DEFAULT_SIZE,
+ 0,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ {
+ // The hard-coded default Reactor size failed, so attempt to
+ // determine the size at run-time by checking the process file
+ // descriptor limit on platforms that support this feature.
+
+ // There is no need to deallocate resources from previous open()
+ // call since the open() method deallocates any resources prior
+ // to exiting if an error was encountered.
+
+ // Set the default reactor size to be the current limit on the
+ // number of file descriptors available to the process. This
+ // size is not necessarily the maximum limit.
+ if (this->open (ACE::max_handles (),
+ 0,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Select_Reactor_T::open ")
+ ACE_LIB_TEXT ("failed inside ")
+ ACE_LIB_TEXT ("ACE_Select_Reactor_T::CTOR")));
+ }
+}
+
+// Initialize ACE_Select_Reactor_T.
+
+template <class ACE_SELECT_REACTOR_TOKEN>
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ACE_Select_Reactor_T
+ (size_t size,
+ int rs,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify,
+ int mask_signals)
+ : token_ (*this),
+ lock_adapter_ (token_),
+ deactivated_ (0),
+ mask_signals_ (mask_signals)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
+
+ if (this->open (size,
+ rs,
+ sh,
+ tq,
+ disable_notify_pipe,
+ notify) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Select_Reactor_T::open ")
+ ACE_LIB_TEXT ("failed inside ACE_Select_Reactor_T::CTOR")));
+}
+
+// Close down the ACE_Select_Reactor_T instance, detaching any
+// remaining Event_Handers. This had better be called from the main
+// event loop thread...
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::close (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::close");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ if (this->delete_signal_handler_)
+ {
+ delete this->signal_handler_;
+ this->signal_handler_ = 0;
+ this->delete_signal_handler_ = 0;
+ }
+
+ this->handler_rep_.close ();
+
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = 0;
+ }
+
+ if (this->notify_handler_ != 0)
+ this->notify_handler_->close ();
+
+ if (this->delete_notify_handler_)
+ {
+ delete this->notify_handler_;
+ this->notify_handler_ = 0;
+ this->delete_notify_handler_ = 0;
+ }
+
+ this->initialized_ = 0;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::current_info
+ (ACE_HANDLE, size_t &)
+{
+ return -1;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN>
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::~ACE_Select_Reactor_T (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::~ACE_Select_Reactor_T");
+ this->close ();
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler_i
+ (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler_i");
+ ACE_HANDLE h;
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->remove_handler_i (h, mask) == -1)
+ return -1;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler_i
+ (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler_i");
+ ACE_HANDLE h;
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->register_handler_i (h, handler, mask) == -1)
+ return -1;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
+ (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
+
+ int result = 0;
+
+#if (ACE_NSIG > 0) && !defined (CHORUS)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (sigset.is_member (s)
+ && this->signal_handler_->register_handler (s,
+ new_sh,
+ new_disp) == -1)
+ result = -1;
+#else /* ACE_NSIG <= 0 || CHORUS */
+ ACE_UNUSED_ARG (sigset);
+ ACE_UNUSED_ARG (new_sh);
+ ACE_UNUSED_ARG (new_disp);
+#endif /* ACE_NSIG <= 0 || CHORUS */
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
+ (const ACE_Sig_Set &sigset)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
+ int result = 0;
+
+#if (ACE_NSIG > 0) && !defined (CHORUS)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (sigset.is_member (s)
+ && this->signal_handler_->remove_handler (s) == -1)
+ result = -1;
+#else /* ACE_NSIG <= 0 || CHORUS */
+ ACE_UNUSED_ARG (sigset);
+#endif /* ACE_NSIG <= 0 || CHORUS */
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> long
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::schedule_timer
+ (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ return this->timer_queue_->schedule
+ (handler,
+ arg,
+ timer_queue_->gettimeofday () + delay_time,
+ interval);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::reset_timer_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ return this->timer_queue_->reset_interval (timer_id, interval);
+}
+
+// Main event loop driver that blocks for <max_wait_time> before
+// returning (will return earlier if I/O or signal events occur).
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events
+ (ACE_Time_Value &max_wait_time)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handle_events");
+
+ return this->handle_events (&max_wait_time);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_error (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handle_error");
+ if (errno == EINTR)
+ return this->restart_;
+#if defined (__MVS__) || defined (ACE_WIN32) || defined (VXWORKS)
+ // On MVS Open Edition and Win32, there can be a number of failure
+ // codes on a bad socket, so check_handles on anything other than
+ // EINTR. VxWorks doesn't even bother to always set errno on error
+ // in select (specifically, it doesn't return EBADF for bad FDs).
+ else
+ return this->check_handles ();
+#else
+# if defined (ACE_PSOS)
+ else if (errno == EBADS)
+ return this->check_handles ();
+# else
+ else if (errno == EBADF)
+ return this->check_handles ();
+# endif /* ACE_PSOS */
+ else
+ return -1;
+#endif /* __MVS__ || ACE_WIN32 */
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::notify_handle
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Handle_Set &ready_mask,
+ ACE_Event_Handler *event_handler,
+ ACE_EH_PTMF ptmf)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::notify_handle");
+ // Check for removed handlers.
+ if (event_handler == 0)
+ return;
+
+ int status = (event_handler->*ptmf) (handle);
+
+ if (status < 0)
+ this->remove_handler_i (handle, mask);
+ else if (status > 0)
+ ready_mask.set_bit (handle);
+}
+
+// Perform GET, CLR, SET, and ADD operations on the select()
+// Handle_Sets.
+//
+// GET = 1, Retrieve current value
+// SET = 2, Set value of bits to new mask (changes the entire mask)
+// ADD = 3, Bitwise "or" the value into the mask (only changes
+// enabled bits)
+// CLR = 4 Bitwise "and" the negation of the value out of the mask
+// (only changes enabled bits)
+//
+// Returns the original mask.
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::mask_ops
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::mask_ops");
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+ return this->bit_ops (handle, mask,
+ this->wait_set_,
+ ops);
+}
+
+// Must be called with locks held.
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **handler)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handler_i");
+ ACE_Event_Handler *h = this->handler_rep_.find (handle);
+
+ if (h == 0)
+ return -1;
+ else
+ {
+ if ((ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK)
+ || ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ && this->wait_set_.rd_mask_.is_set (handle) == 0)
+ return -1;
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK)
+ && this->wait_set_.wr_mask_.is_set (handle) == 0)
+ return -1;
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK)
+ && this->wait_set_.ex_mask_.is_set (handle) == 0)
+ return -1;
+ }
+
+ if (handler != 0)
+ *handler = h;
+ return 0;
+}
+
+// Must be called with locks held
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_i (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::resume_i");
+ if (this->handler_rep_.find (handle) == 0)
+ return -1;
+
+ if (this->suspend_set_.rd_mask_.is_set (handle))
+ {
+ this->wait_set_.rd_mask_.set_bit (handle);
+ this->suspend_set_.rd_mask_.clr_bit (handle);
+ }
+ if (this->suspend_set_.wr_mask_.is_set (handle))
+ {
+ this->wait_set_.wr_mask_.set_bit (handle);
+ this->suspend_set_.wr_mask_.clr_bit (handle);
+ }
+ if (this->suspend_set_.ex_mask_.is_set (handle))
+ {
+ this->wait_set_.ex_mask_.set_bit (handle);
+ this->suspend_set_.ex_mask_.clr_bit (handle);
+ }
+ return 0;
+}
+
+// Must be called with locks held
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_i (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::suspend_i");
+ if (this->handler_rep_.find (handle) == 0)
+ return -1;
+
+ if (this->wait_set_.rd_mask_.is_set (handle))
+ {
+ this->suspend_set_.rd_mask_.set_bit (handle);
+ this->wait_set_.rd_mask_.clr_bit (handle);
+ }
+ if (this->wait_set_.wr_mask_.is_set (handle))
+ {
+ this->suspend_set_.wr_mask_.set_bit (handle);
+ this->wait_set_.wr_mask_.clr_bit (handle);
+ }
+ if (this->wait_set_.ex_mask_.is_set (handle))
+ {
+ this->suspend_set_.ex_mask_.set_bit (handle);
+ this->wait_set_.ex_mask_.clr_bit (handle);
+ }
+ return 0;
+}
+
+// Must be called with locks held
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::is_suspended_i (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::is_suspended_i");
+ if (this->handler_rep_.find (handle) == 0)
+ return 0;
+
+ return this->suspend_set_.rd_mask_.is_set (handle) ||
+ this->suspend_set_.wr_mask_.is_set (handle) ||
+ this->suspend_set_.ex_mask_.is_set (handle) ;
+
+}
+
+// Must be called with locks held
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler_i
+ (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler_i");
+
+ // Insert the <handle, event_handle> tuple into the Handler
+ // Repository.
+ return this->handler_rep_.bind (handle, event_handler, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler_i
+ (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler_i");
+
+ // Unbind this handle.
+ return this->handler_rep_.unbind (handle, mask);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::work_pending (const ACE_Time_Value &timeout)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ u_long width = (u_long) this->handler_rep_.max_handlep1 ();
+
+ ACE_Select_Reactor_Handle_Set fd_set;
+ fd_set.rd_mask_ = this->wait_set_.rd_mask_;
+ fd_set.wr_mask_ = this->wait_set_.wr_mask_;
+ fd_set.ex_mask_ = this->wait_set_.ex_mask_;
+
+ return ACE_OS::select (int (width),
+ fd_set.rd_mask_,
+ fd_set.wr_mask_,
+ fd_set.ex_mask_,
+ timeout);
+}
+
+// Must be called with lock held.
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::wait_for_multiple_events
+ (ACE_Select_Reactor_Handle_Set &dispatch_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::wait_for_multiple_events");
+ u_long width = 0;
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value *this_timeout = &timer_buf;
+
+ int number_of_active_handles = this->any_ready (dispatch_set);
+
+ // If there are any bits enabled in the <ready_set_> then we'll
+ // handle those first, otherwise we'll block in <select>.
+
+ if (number_of_active_handles == 0)
+ {
+ do
+ {
+ if (this->timer_queue_->calculate_timeout (max_wait_time,
+ this_timeout) == 0)
+ this_timeout = 0;
+
+ width = (u_long) this->handler_rep_.max_handlep1 ();
+
+ dispatch_set.rd_mask_ = this->wait_set_.rd_mask_;
+ dispatch_set.wr_mask_ = this->wait_set_.wr_mask_;
+ dispatch_set.ex_mask_ = this->wait_set_.ex_mask_;
+ number_of_active_handles = ACE_OS::select (int (width),
+ dispatch_set.rd_mask_,
+ dispatch_set.wr_mask_,
+ dispatch_set.ex_mask_,
+ this_timeout);
+ }
+ while (number_of_active_handles == -1 && this->handle_error () > 0);
+
+ if (number_of_active_handles > 0)
+ {
+#if !defined (ACE_WIN32)
+ // Resynchronize the fd_sets so their "max" is set properly.
+ dispatch_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
+ dispatch_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
+ dispatch_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_WIN32 */
+ }
+ }
+
+ // Return the number of events to dispatch.
+ return number_of_active_handles;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_timer_handlers
+ (int &number_of_handlers_dispatched)
+{
+ number_of_handlers_dispatched += this->timer_queue_->expire ();
+ if (this->state_changed_)
+ return -1;
+ else
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_notification_handlers
+ (ACE_Select_Reactor_Handle_Set &dispatch_set,
+ int &number_of_active_handles,
+ int &number_of_handlers_dispatched)
+{
+ // Check to see if the ACE_HANDLE associated with the
+ // Select_Reactor's notify hook is enabled. If so, it means that
+ // one or more other threads are trying to update the
+ // ACE_Select_Reactor_T's internal tables or the notify pipe is
+ // enabled. We'll handle all these threads and notifications, and
+ // then break out to continue the event loop.
+
+ int n = this->notify_handler_->dispatch_notifications (number_of_active_handles,
+ dispatch_set.rd_mask_);
+ if (n == -1)
+ return -1;
+ else
+ number_of_handlers_dispatched += n;
+
+ return this->state_changed_ ? -1 : 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_io_set
+ (int number_of_active_handles,
+ int &number_of_handlers_dispatched,
+ int mask,
+ ACE_Handle_Set &dispatch_mask,
+ ACE_Handle_Set &ready_mask,
+ ACE_EH_PTMF callback)
+{
+ ACE_HANDLE handle;
+
+ ACE_Handle_Set_Iterator handle_iter (dispatch_mask);
+
+ while ((handle = handle_iter ()) != ACE_INVALID_HANDLE
+ && number_of_handlers_dispatched < number_of_active_handles
+ && this->state_changed_ == 0)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Select_Reactor_T::dispatching\n")));
+ number_of_handlers_dispatched++;
+ this->notify_handle (handle,
+ mask,
+ ready_mask,
+ this->handler_rep_.find (handle),
+ callback);
+ }
+
+ if (number_of_handlers_dispatched > 0 && this->state_changed_)
+ return -1;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_io_handlers
+ (ACE_Select_Reactor_Handle_Set &dispatch_set,
+ int &number_of_active_handles,
+ int &number_of_handlers_dispatched)
+{
+ // Handle output events (this code needs to come first to handle the
+ // obscure case of piggy-backed data coming along with the final
+ // handshake message of a nonblocking connection).
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Select_Reactor_T::dispatch - WRITE\n")));
+ if (this->dispatch_io_set (number_of_active_handles,
+ number_of_handlers_dispatched,
+ ACE_Event_Handler::WRITE_MASK,
+ dispatch_set.wr_mask_,
+ this->ready_set_.wr_mask_,
+ &ACE_Event_Handler::handle_output) == -1)
+ {
+ number_of_active_handles -= number_of_handlers_dispatched;
+ return -1;
+ }
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Select_Reactor_T::dispatch - EXCEPT\n")));
+ if (this->dispatch_io_set (number_of_active_handles,
+ number_of_handlers_dispatched,
+ ACE_Event_Handler::EXCEPT_MASK,
+ dispatch_set.ex_mask_,
+ this->ready_set_.ex_mask_,
+ &ACE_Event_Handler::handle_exception) == -1)
+ {
+ number_of_active_handles -= number_of_handlers_dispatched;
+ return -1;
+ }
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Select_Reactor_T::dispatch - READ\n")));
+ if (this->dispatch_io_set (number_of_active_handles,
+ number_of_handlers_dispatched,
+ ACE_Event_Handler::READ_MASK,
+ dispatch_set.rd_mask_,
+ this->ready_set_.rd_mask_,
+ &ACE_Event_Handler::handle_input) == -1)
+ {
+ number_of_active_handles -= number_of_handlers_dispatched;
+ return -1;
+ }
+
+ number_of_active_handles -= number_of_handlers_dispatched;
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch
+ (int active_handle_count,
+ ACE_Select_Reactor_Handle_Set &dispatch_set)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::dispatch");
+
+ int io_handlers_dispatched = 0;
+ int other_handlers_dispatched = 0;
+ int signal_occurred = 0;
+ // The following do/while loop keeps dispatching as long as there
+ // are still active handles. Note that the only way we should ever
+ // iterate more than once through this loop is if signals occur
+ // while we're dispatching other handlers.
+
+ do
+ {
+ // Note that we keep track of changes to our state. If any of
+ // the dispatch_*() methods below return -1 it means that the
+ // <wait_set_> state has changed as the result of an
+ // <ACE_Event_Handler> being dispatched. This means that we
+ // need to bail out and rerun the select() loop since our
+ // existing notion of handles in <dispatch_set> may no longer be
+ // correct.
+ //
+ // In the beginning, our state starts out unchanged. After
+ // every iteration (i.e., due to signals), our state starts out
+ // unchanged again.
+
+ this->state_changed_ = 0;
+
+ // Perform the Template Method for dispatching all the handlers.
+
+ // First check for interrupts.
+ if (active_handle_count == -1)
+ {
+ // Bail out -- we got here since <select> was interrupted.
+ if (ACE_Sig_Handler::sig_pending () != 0)
+ {
+ ACE_Sig_Handler::sig_pending (0);
+
+ // If any HANDLES in the <ready_set_> are activated as a
+ // result of signals they should be dispatched since
+ // they may be time critical...
+ active_handle_count = this->any_ready (dispatch_set);
+
+ // Record the fact that the Reactor has dispatched a
+ // handle_signal() method. We need this to return the
+ // appropriate count below.
+ signal_occurred = 1;
+ }
+ else
+ return -1;
+ }
+
+ // Handle timers early since they may have higher latency
+ // constraints than I/O handlers. Ideally, the order of
+ // dispatching should be a strategy...
+ else if (this->dispatch_timer_handlers (other_handlers_dispatched) == -1)
+ // State has changed or timer queue has failed, exit loop.
+ break;
+
+ // Check to see if there are no more I/O handles left to
+ // dispatch AFTER we've handled the timers...
+ else if (active_handle_count == 0)
+ return io_handlers_dispatched
+ + other_handlers_dispatched
+ + signal_occurred;
+
+ // Next dispatch the notification handlers (if there are any to
+ // dispatch). These are required to handle multi-threads that
+ // are trying to update the <Reactor>.
+
+ else if (this->dispatch_notification_handlers
+ (dispatch_set,
+ active_handle_count,
+ other_handlers_dispatched) == -1)
+ // State has changed or a serious failure has occured, so exit
+ // loop.
+ break;
+
+ // Finally, dispatch the I/O handlers.
+ else if (this->dispatch_io_handlers
+ (dispatch_set,
+ active_handle_count,
+ io_handlers_dispatched) == -1)
+ // State has changed, so exit loop.
+ break;
+ }
+ while (active_handle_count > 0);
+
+ return io_handlers_dispatched + other_handlers_dispatched + signal_occurred;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::release_token (void)
+{
+#if defined (ACE_WIN32)
+ this->token_.release ();
+ return (int) EXCEPTION_CONTINUE_SEARCH;
+#else
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events
+ (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handle_events");
+
+ // Stash the current time -- the destructor of this object will
+ // automatically compute how much time elpased since this method was
+ // called.
+ ACE_Countdown_Time countdown (max_wait_time);
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1);
+
+ if (ACE_OS::thr_equal (ACE_Thread::self (),
+ this->owner_) == 0 || this->deactivated_)
+ return -1;
+
+ // Update the countdown to reflect time waiting for the mutex.
+ countdown.update ();
+#else
+ if (this->deactivated_)
+ return -1;
+#endif /* ACE_MT_SAFE */
+
+ return this->handle_events_i (max_wait_time);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events_i
+ (ACE_Time_Value *max_wait_time)
+{
+ int result = -1;
+
+ ACE_SEH_TRY
+ {
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ int number_of_active_handles =
+ this->wait_for_multiple_events (dispatch_set,
+ max_wait_time);
+
+ result = this->dispatch (number_of_active_handles,
+ dispatch_set);
+ }
+ ACE_SEH_EXCEPT (this->release_token ())
+ {
+ // As it stands now, we catch and then rethrow all Win32
+ // structured exceptions so that we can make sure to release the
+ // <token_> lock correctly.
+ }
+
+ this->state_changed_ = 1;
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::check_handles (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::check_handles");
+
+#if defined (ACE_WIN32) || defined (__MVS__) || defined (ACE_PSOS) || defined (VXWORKS)
+ ACE_Time_Value time_poll = ACE_Time_Value::zero;
+ ACE_Handle_Set rd_mask;
+#endif /* ACE_WIN32 || MVS || ACE_PSOS || VXWORKS */
+
+ ACE_Event_Handler *eh = 0;
+ int result = 0;
+
+ for (ACE_Select_Reactor_Handler_Repository_Iterator iter (&this->handler_rep_);
+ iter.next (eh) != 0;
+ iter.advance ())
+ {
+ ACE_HANDLE handle = eh->get_handle ();
+
+ // Skip back to the beginning of the loop if the HANDLE is
+ // invalid.
+ if (handle == ACE_INVALID_HANDLE)
+ continue;
+
+#if defined (ACE_WIN32) || defined (__MVS__) || defined (ACE_PSOS) || defined (VXWORKS)
+ // Win32 needs to do the check this way because fstat won't work on
+ // a socket handle. MVS Open Edition needs to do it this way because,
+ // even though the docs say to check a handle with either select or
+ // fstat, the fstat method always says the handle is ok.
+ // pSOS needs to do it this way because file handles and socket handles
+ // are maintained by separate pieces of the system. VxWorks needs the select
+ // variant since fstat always returns an error on socket FDs.
+ rd_mask.set_bit (handle);
+
+ if (ACE_OS::select (int (handle) + 1,
+ rd_mask, 0, 0,
+ &time_poll) < 0)
+ {
+ result = 1;
+ this->remove_handler_i (handle,
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ }
+ rd_mask.clr_bit (handle);
+#else /* !ACE_WIN32 && !MVS && !ACE_PSOS */
+ struct stat temp;
+
+ if (ACE_OS::fstat (handle, &temp) == -1)
+ {
+ result = 1;
+ this->remove_handler_i (handle,
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ }
+#endif /* ACE_WIN32 || MVS || ACE_PSOS */
+ }
+
+ return result;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dump (void) const
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ this->timer_queue_->dump ();
+ this->handler_rep_.dump ();
+ this->signal_handler_->dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("delete_signal_handler_ = %d\n"),
+ this->delete_signal_handler_));
+
+ ACE_HANDLE h;
+
+ for (ACE_Handle_Set_Iterator handle_iter_wr (this->wait_set_.wr_mask_);
+ (h = handle_iter_wr ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_wr)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("write_handle = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_rd (this->wait_set_.rd_mask_);
+ (h = handle_iter_rd ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_rd)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("read_handle = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_ex (this->wait_set_.ex_mask_);
+ (h = handle_iter_ex ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_ex)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("except_handle = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_wr_ready (this->ready_set_.wr_mask_);
+ (h = handle_iter_wr_ready ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_wr_ready)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("write_handle_ready = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_rd_ready (this->ready_set_.rd_mask_);
+ (h = handle_iter_rd_ready ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_rd_ready)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("read_handle_ready = %d\n"), h));
+
+ for (ACE_Handle_Set_Iterator handle_iter_ex_ready (this->ready_set_.ex_mask_);
+ (h = handle_iter_ex_ready ()) != ACE_INVALID_HANDLE;
+ ++handle_iter_ex_ready)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("except_handle_ready = %d\n"), h));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("restart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nrequeue_position_ = %d\n"), this->requeue_position_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ninitialized_ = %d\n"), this->initialized_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nowner_ = %d\n"), this->owner_));
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->dump ();
+ this->token_.dump ();
+#endif /* ACE_MT_SAFE */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+#endif /* ACE_SELECT_REACTOR_T_C */
diff --git a/ace/Demux/Select_Reactor_T.h b/ace/Demux/Select_Reactor_T.h
new file mode 100644
index 00000000000..66db768828e
--- /dev/null
+++ b/ace/Demux/Select_Reactor_T.h
@@ -0,0 +1,770 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Select_Reactor_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SELECT_REACTOR_T_H
+#define ACE_SELECT_REACTOR_T_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor_Base.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Select_Reactor_Token_T
+ *
+ * @brief Used as a synchronization mechanism to coordinate concurrent
+ * access to a Select_Reactor object.
+ *
+ * This class is used to make the <ACE_Select_Reactor>
+ * thread-safe. By default, the thread that runs the
+ * <handle_events> loop holds the token, even when it is blocked
+ * in the <select> call. Whenever another thread wants to
+ * access the <ACE_Reactor> via its <register_handler>,
+ * <remove_handler>, etc. methods) it must ask the token owner
+ * for temporary release of the token. To accomplish this, the
+ * owner of a token must define a <sleep_hook> through which it
+ * can be notified to temporarily release the token if the
+ * current situation permits this.
+ * The owner of the token is responsible for deciding which
+ * request for the token can be granted. By using the
+ * <ACE_Token::renew> API, the thread that releases the token
+ * temporarily can specify to get the token back right after the
+ * other thread has completed using the token. Thus, there is a
+ * dedicated thread that owns the token ``by default.'' This
+ * thread grants other threads access to the token by ensuring
+ * that whenever somebody else has finished using the token the
+ * ``default owner'' first holds the token again, i.e., the
+ * owner has the chance to schedule other threads.
+ * The thread that most likely needs the token most of the time
+ * is the thread running the dispatch loop. Typically the token
+ * gets released prior to entering the <select> call and gets
+ * ``re-acquired'' as soon as the <select> call returns, which
+ * results probably in many calls to <release>/<acquire> that
+ * are not really needed since no other thread would need the
+ * token in the meantime. That's why the dispatcher thread is
+ * chosen to be the owner of the token.
+ * In case the token would have been released while in <select>
+ * there would be a good chance that the <fd_set> could have
+ * been modified while the <select> returns from blocking and
+ * trying to re-acquire the lock. Through the token mechanism
+ * it is ensured that while another thread is holding the token,
+ * the dispatcher thread is blocked in the <renew> call and not
+ * in <select>. Thus, it is not critical to change the
+ * <fd_set>. The implementation of the <sleep_hook> mechanism
+ * provided by the <ACE_Select_Reactor_Token> enables the
+ * default owner to be the thread that executes the dispatch
+ * loop.
+ */
+template <class ACE_SELECT_REACTOR_MUTEX>
+class ACE_Select_Reactor_Token_T : public ACE_SELECT_REACTOR_MUTEX
+{
+public:
+ ACE_Select_Reactor_Token_T (ACE_Select_Reactor_Impl &r);
+ ACE_Select_Reactor_Token_T (void);
+ virtual ~ACE_Select_Reactor_Token_T (void);
+
+ /// Called just before the ACE_Event_Handler goes to sleep.
+ virtual void sleep_hook (void);
+
+ /// Set/Get methods
+ ACE_Select_Reactor_Impl &select_reactor (void);
+ void select_reactor (ACE_Select_Reactor_Impl &);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_Select_Reactor_Impl *select_reactor_;
+};
+
+/**
+ * @class ACE_Select_Reactor_T
+ *
+ * @brief An object oriented event demultiplexor and event handler
+ * dispatcher.
+ *
+ * The <ACE_Select_Reactor> is an object-oriented event
+ * demultiplexor and event handler dispatcher. The sources of
+ * events that the <ACE_Select_Reactor> waits for and dispatches
+ * includes I/O events, signals, and timer events. All public
+ * methods acquire the main <ACE_Select_Reactor_Token> lock and
+ * call down to private or protected methods, which assume that
+ * the lock is held and so therefore don't (re)acquire the lock.
+ */
+template <class ACE_SELECT_REACTOR_TOKEN>
+class ACE_Select_Reactor_T : public ACE_Select_Reactor_Impl
+{
+public:
+ // = Initialization and termination methods.
+
+ /// If <disable_notify_pipe> is non-0 then the reactor will
+ /// not create a notification pipe, which will save two I/O handles
+ /// but will elide the <notify()> feature. If <mask_signals> is
+ /// 1 the reactor is "signal-safe" when dispatching handlers to
+ /// signal events, whereas if <mask_signals> is 0 the reactor will
+ /// be more efficient, but not signal-safe (which may be perfectly
+ /// fine if your application doesn't use the reactor to handle signals).
+ ACE_Select_Reactor_T (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1);
+
+ /// Initialize @c ACE_Select_Reactor with size @arg size.
+ /// If @arg disable_notify_pipe is non-0 then the reactor will
+ /// not create a notification pipe, which will save two I/O handles
+ /// but will elide the notification feature. If @arg mask_signals is
+ /// 1 the reactor is "signal-safe" when dispatching handlers to
+ /// signal events, whereas if @arg mask_signals is 0 the reactor will
+ /// be more efficient, but not signal-safe (which may be perfectly
+ /// fine if your application doesn't use the reactor to handle signals).
+ /**
+ * @note On Unix platforms, the size parameter should be as large as
+ * the maximum number of file descriptors allowed for a given
+ * process. This is necessary since a file descriptor is used
+ * to directly index the array of event handlers maintained by
+ * the Reactor's handler repository. Direct indexing is used
+ * for efficiency reasons.
+ */
+ ACE_Select_Reactor_T (size_t size,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify *notify = 0,
+ int mask_signals = 1);
+
+ /**
+ * Initialize the @c ACE_Select_Reactor to manage
+ * @arg max_number_of_handles. If @arg restart is non-0 then the
+ * @c ACE_Reactor's @c handle_events method will be restarted
+ * automatically when @c EINTR occurs. If @arg signal_handler or
+ * @arg timer_queue are non-0 they are used as the signal handler and
+ * timer queue, respectively. If @arg disable_notify_pipe is non-0 the
+ * notification pipe is not created, thereby saving two I/O handles.
+ *
+ * @note On Unix platforms, the maximum_number_of_handles parameter
+ * should be as large as the maximum number of file
+ * descriptors allowed for a given process. This is necessary
+ * since a file descriptor is used to directly index the array
+ * of event handlers maintained by the Reactor's handler
+ * repository. Direct indexing is used for efficiency
+ * reasons.
+ */
+ virtual int open (size_t max_number_of_handles = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify * = 0);
+
+ /// Returns -1 (not used in this implementation);
+ virtual int current_info (ACE_HANDLE, size_t & /* size */);
+
+ /// Use a user specified signal handler instead.
+ virtual int set_sig_handler (ACE_Sig_Handler *signal_handler);
+
+ // = The following method is deprecated. Use <timer_queue> instead.
+ /// Set a user specified timer queue.
+ virtual int set_timer_queue (ACE_Timer_Queue *tq);
+
+ /// Set a user-specified timer queue.
+ /// Return the current <ACE_Timer_Queue>.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+ virtual ACE_Timer_Queue *timer_queue (void) const;
+
+ /// Close down the select_reactor and release all of its resources.
+ virtual int close (void);
+
+ /// Close down the select_reactor and release all of its resources.
+ virtual ~ACE_Select_Reactor_T (void);
+
+ // = Event loop drivers.
+
+ /**
+ * Returns non-zero if there are I/O events "ready" for dispatching,
+ * but does not actually dispatch the event handlers. By default,
+ * don't block while checking this, i.e., "poll".
+ */
+ virtual int work_pending (const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
+
+ /**
+ * This event loop driver that blocks for <max_wait_time> before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that <max_wait_time> can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * Returns the total number of I/O and Timer <ACE_Event_Handler>s
+ * that were dispatched, 0 if the <max_wait_time> elapsed without
+ * dispatching any handlers, or -1 if something goes wrong.
+ *
+ * Current <alertable_handle_events> is identical to
+ * <handle_events>.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+ virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ /**
+ * This method is just like the one above, except the
+ * <max_wait_time> value is a reference and can therefore never be
+ * NULL.
+ *
+ * Current <alertable_handle_events> is identical to
+ * <handle_events>.
+ */
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+ virtual int alertable_handle_events (ACE_Time_Value &max_wait_time);
+
+ // = Event handling control.
+
+ /**
+ * Return the status of Reactor. If this function returns 0, the reactor is
+ * actively handling events. If it returns non-zero, <handling_events> and
+ * <handle_alertable_events> return -1 immediately.
+ */
+ virtual int deactivated (void);
+
+ /**
+ * Control whether the Reactor will handle any more incoming events or not.
+ * If <do_stop> == 1, the Reactor will be disabled. By default, a reactor
+ * is in active state and can be deactivated/reactived as wish.
+ */
+ virtual void deactivate (int do_stop);
+
+ // = Register and remove <ACE_Event_Handler>s.
+ /**
+ * Register a <eh> with a particular <mask>. Note that the
+ * <Select_Reactor> will call <ACE_Event_Handler::get_handle> to
+ * extract the underlying I/O handle.
+ */
+ virtual int register_handler (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register a <eh> with a particular <mask>. Note that since the
+ * <handle> is given the Select_Reactor will *not* call
+ * <ACE_Event_Handler::get_handle> to extract the underlying I/O
+ * handle.
+ */
+ virtual int register_handler (ACE_HANDLE handle,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+#if defined (ACE_WIN32)
+
+ // Originally this interface was available for all platforms, but
+ // because ACE_HANDLE is an int on non-Win32 platforms, compilers
+ // are not able to tell the difference between
+ // register_handler(ACE_Event_Handler*,ACE_Reactor_Mask) and
+ // register_handler(ACE_Event_Handler*,ACE_HANDLE). Therefore, we
+ // have restricted this method to Win32 only.
+
+ /// Not implemented.
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE);
+
+#endif /* ACE_WIN32 */
+
+ /// Not implemented.
+ virtual int register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register <eh> with all the <handles> in the <Handle_Set>.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register <new_sh> to handle the signal <signum> using the
+ * <new_disp>. Returns the <old_sh> that was previously registered
+ * (if any), along with the <old_disp> of the signal handler.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /// Registers <new_sh> to handle a set of signals <sigset> using the
+ /// <new_disp>.
+ virtual int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0);
+
+ /**
+ * Removes the <mask> binding of <eh> from the Select_Reactor. If
+ * there are no more bindings for this <eh> then it is removed from
+ * the Select_Reactor. Note that the Select_Reactor will call
+ * <ACE_Event_Handler::get_handle> to extract the underlying I/O
+ * handle.
+ */
+ virtual int remove_handler (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes the <mask> bind of <Event_Handler> whose handle is
+ * <handle> from the Select_Reactor. If there are no more bindings
+ * for this <eh> then it is removed from the Select_Reactor.
+ */
+ virtual int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask);
+
+ /**
+ * Removes all the <mask> bindings for handles in the <handle_set>
+ * bind of <Event_Handler>. If there are no more bindings for any
+ * of these handlers then they are removed from the Select_Reactor.
+ */
+ virtual int remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask);
+
+ /**
+ * Remove the ACE_Event_Handler currently associated with <signum>.
+ * <sigkey> is ignored in this implementation since there is only
+ * one instance of a signal handler. Install the new disposition
+ * (if given) and return the previous disposition (if desired by the
+ * caller). Returns 0 on success and -1 if <signum> is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ /// Calls <remove_handler> for every signal in <sigset>.
+ virtual int remove_handler (const ACE_Sig_Set &sigset);
+
+ // = Suspend and resume Handlers.
+
+ /// Temporarily suspend the <Event_Handler> associated with <eh>.
+ virtual int suspend_handler (ACE_Event_Handler *eh);
+
+ /// Temporarily suspend the <Event_Handler> associated with <handle>.
+ virtual int suspend_handler (ACE_HANDLE handle);
+
+ /// Suspend all <handles> in handle set temporarily.
+ virtual int suspend_handler (const ACE_Handle_Set &handles);
+
+ /// Suspend all the <Event_Handlers> in the Select_Reactor.
+ virtual int suspend_handlers (void);
+
+ /// Resume a temporarily suspend <Event_Handler> associated with
+ /// <eh>.
+ virtual int resume_handler (ACE_Event_Handler *eh);
+
+ /// Resume a temporarily suspended <Event_Handler> associated with
+ /// <handle>.
+ virtual int resume_handler (ACE_HANDLE handle);
+
+ /// Resume all <handles> in handle set.
+ virtual int resume_handler (const ACE_Handle_Set &handles);
+
+ /// Resume all the <Event_Handlers> in the Select_Reactor.
+ virtual int resume_handlers (void);
+
+ /**
+ * Return 1 if we any event associations were made by the reactor
+ * for the handles that it waits on, 0 otherwise. Since the
+ * Select_Reactor does not do any event associations, this function
+ * always return 0.
+ */
+ virtual int uses_event_associations (void);
+
+ // = Timer management.
+ /**
+ * Schedule an ACE_Event_Handler that will expire after an amount
+ * of time. The return value of this method, a timer_id value,
+ * uniquely identifies the event_handler in the ACE_Reactor's
+ * internal list of timers.
+ * This timer_id value can be used to cancel the timer
+ * with the cancel_timer() call.
+ *
+ * @see cancel_timer()
+ * @see reset_timer_interval()
+ *
+ * @param event_handler event handler to schedule on reactor
+ * @param arg argument passed to the handle_timeout() method of event_handler
+ * @param delta time interval after which the timer will expire
+ * @param interval time interval after which the timer will be automatically rescheduled
+ * @return -1 on failure, a timer_id value on success
+ */
+ virtual long schedule_timer (ACE_Event_Handler *,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /**
+ * Resets the interval of the timer represented by <timer_id> to
+ * <interval>, which is specified in relative time to the current
+ * <gettimeofday>. If <interval> is equal to
+ * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
+ * timer. Returns 0 if successful, -1 if not.
+ */
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /**
+ * Cancel all <event_handlers> that match the address of
+ * <event_handler>. If <dont_call_handle_close> is 0 then the
+ * <handle_close> method of <event_handler> will be invoked.
+ * Returns number of handler's cancelled.
+ */
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single <ACE_Event_Handler> that matches the <timer_id>
+ * value (which was returned from the <schedule> method). If arg is
+ * non-NULL then it will be set to point to the ``magic cookie''
+ * argument passed in when the <Event_Handler> was registered. This
+ * makes it possible to free up the memory and avoid memory leaks.
+ * If <dont_call_handle_close> is 0 then the <handle_close> method
+ * of <event_handler> will be invoked. Returns 1 if cancellation
+ * succeeded and 0 if the <timer_id> wasn't found.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+ // = High-level Event_Handler scheduling operations
+
+ /// ADD the dispatch MASK "bit" bound with the <eh> and the <mask>.
+ virtual int schedule_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// ADD the dispatch MASK "bit" bound with the <handle> and the <mask>.
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// CLR the dispatch MASK "bit" bound with the <eh> and the <mask>.
+ virtual int cancel_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// CLR the dispatch MASK "bit" bound with the <handle> and the <mask>.
+ virtual int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ // = Notification methods.
+ /**
+ * Called by a thread when it wants to unblock the Select_Reactor.
+ * This wakeups the <ACE_Select_Reactor> if currently blocked in
+ * <select>/<poll>. Pass over both the <Event_Handler> *and* the
+ * <mask> to allow the caller to dictate which <Event_Handler>
+ * method the <Select_Reactor> will invoke. The <ACE_Time_Value>
+ * indicates how long to blocking trying to notify the
+ * <Select_Reactor>. If <timeout> == 0, the caller will block until
+ * action is possible, else will wait until the relative time
+ * specified in *<timeout> elapses).
+ */
+ virtual int notify (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 0);
+
+ /**
+ * Set the maximum number of times that the
+ * <ACE_Select_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify pipe before breaking out of its <recv> loop. By default,
+ * this is set to -1, which means "iterate until the pipe is empty."
+ * Setting this to a value like "1 or 2" will increase "fairness"
+ * (and thus prevent starvation) at the expense of slightly higher
+ * dispatching overhead.
+ */
+ virtual void max_notify_iterations (int);
+
+ /**
+ * Get the maximum number of times that the
+ * <ACE_Select_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify pipe before breaking out of its <recv> loop.
+ */
+ virtual int max_notify_iterations (void);
+
+ /// Get the existing restart value.
+ virtual int restart (void);
+
+ /// Set a new value for restart and return the original value.
+ virtual int restart (int r);
+
+ /// Set position that the main ACE_Select_Reactor thread is requeued in the
+ /// list of waiters during a <notify> callback.
+ virtual void requeue_position (int);
+
+ /// Get position that the main ACE_Select_Reactor thread is requeued in the
+ /// list of waiters during a <notify> callback.
+ virtual int requeue_position (void);
+
+ // = Low-level wait_set mask manipulation methods.
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the <eh> and
+ /// <mask>.
+ virtual int mask_ops (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <handle>
+ /// and <mask>.
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ // = Low-level ready_set mask manipulation methods.
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <eh> and <mask>.
+ virtual int ready_ops (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// GET/SET/ADD/CLR the ready "bit" bound with the <handle> and <mask>.
+ virtual int ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask,
+ int ops);
+
+ /// Wake up all threads in waiting in the event loop
+ virtual void wakeup_all_threads (void);
+
+ // = Only the owner thread can perform a <handle_events>.
+
+ /// Set the new owner of the thread and return the old owner.
+ virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0);
+
+ /// Return the current owner of the thread.
+ virtual int owner (ACE_thread_t *);
+
+ // = Miscellaneous Handler operations.
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to <mask>. Return the <eh> associated with this <handler>
+ * if <eh> != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **eh = 0);
+
+ /**
+ * Check to see if <signum> is associated with a valid Event_Handler
+ * bound to a signal. Return the <eh> associated with this
+ * <handler> if <eh> != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler ** = 0);
+
+ /// Returns true if we've been successfully initialized, else false.
+ virtual int initialized (void);
+
+ /// Returns the current size of the Reactor's internal descriptor
+ /// table.
+ virtual size_t size (void) const;
+
+ /**
+ * Returns a reference to the <ACE_Select_Reactor_Token> that is
+ * used to serialize the internal Select_Reactor's processing logic.
+ * This can be useful for situations where you need to avoid
+ * deadlock efficiently when <ACE_Event_Handlers> are used in
+ * multiple threads.
+ */
+ virtual ACE_Lock &lock (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Internal methods that do the actual work.
+
+ // All of these methods assume that the <Select_Reactor>'s token
+ // lock is held by the public methods that call down to them.
+
+ /// Do the work of actually binding the <handle> and <eh> with the
+ /// <mask>.
+ virtual int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /// Register a set of <handles>.
+ virtual int register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Do the work of actually unbinding the <handle> and <eh> with the
+ /// <mask>.
+ virtual int remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask);
+
+ /// Remove a set of <handles>.
+ virtual int remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask);
+
+ /// Suspend the <Event_Handler> associated with <handle>
+ virtual int suspend_i (ACE_HANDLE handle);
+
+ /// Check to see if the <Event_Handler> associated with <handle> is
+ /// suspended. Returns 0 if not, 1 if so.
+ virtual int is_suspended_i (ACE_HANDLE handle);
+
+ /// Resume the <Event_Handler> associated with <handle>
+ virtual int resume_i (ACE_HANDLE handle);
+
+ /// Implement the public <handler> method.
+ virtual int handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask,
+ ACE_Event_Handler ** = 0);
+
+ /// Implement the public <handler> method.
+ virtual int handler_i (int signum, ACE_Event_Handler ** = 0);
+
+ /**
+ * Check if there are any HANDLEs enabled in the <ready_set_>, and
+ * if so, update the <handle_set> and return the number ready. If
+ * there aren't any HANDLEs enabled return 0.
+ */
+ virtual int any_ready (ACE_Select_Reactor_Handle_Set &handle_set);
+
+ /// Implement the <any_ready> method, assuming that the Sig_Guard is
+ /// beign held
+ virtual int any_ready_i (ACE_Select_Reactor_Handle_Set &handle_set);
+
+ /// Take corrective action when errors occur.
+ virtual int handle_error (void);
+
+ /// Make sure the handles are all valid.
+ virtual int check_handles (void);
+
+ /// Wait for events to occur.
+ virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+ // = Dispatching methods.
+
+ /**
+ * Template Method that dispatches <ACE_Event_Handler>s for time
+ * events, I/O events, and signal events. Returns the total number
+ * of <ACE_Event_Handler>s that were dispatched or -1 if something
+ * goes wrong.
+ */
+ virtual int dispatch (int nfound,
+ ACE_Select_Reactor_Handle_Set &);
+
+ /**
+ * Dispatch all timer handlers that have expired. Returns -1 if the
+ * state of the <wait_set_> has changed, else 0.
+ * <number_dispatched> is set to the number of timer handlers
+ * dispatched.
+ */
+ virtual int dispatch_timer_handlers (int &number_dispatched);
+
+ /**
+ * Dispatch any notification handlers. Returns -1 if the state of
+ * the <wait_set_> has changed, else returns number of handlers
+ * notified.
+ */
+ virtual int dispatch_notification_handlers (ACE_Select_Reactor_Handle_Set &dispatch_set,
+ int &number_of_active_handles,
+ int &number_of_handlers_dispatched);
+
+ /**
+ * Dispatch all the input/output/except handlers that are enabled in
+ * the <dispatch_set>. Updates <number_of_active_handles> and
+ * <number_of_handlers_dispatched> according to the behavior of the
+ * number Returns -1 if the state of the <wait_set_> has changed,
+ * else 0.
+ */
+ virtual int dispatch_io_handlers (ACE_Select_Reactor_Handle_Set &dispatch_set,
+ int &number_of_active_handles,
+ int &number_of_handlers_dispatched);
+
+ /**
+ * Factors the dispatching of an io handle set (each WRITE, EXCEPT
+ * or READ set of handles). It updates the
+ * <number_of_handlers_dispatched> and invokes this->notify_handle
+ * for all the handles in <dispatch_set> using the <mask>,
+ * <ready_set> and <callback> parameters. Must return -1 if
+ * this->state_changed otherwise it must return 0.
+ */
+ virtual int dispatch_io_set (int number_of_active_handles,
+ int &number_of_handlers_dispatched,
+ int mask,
+ ACE_Handle_Set& dispatch_mask,
+ ACE_Handle_Set& ready_mask,
+ ACE_EH_PTMF callback);
+
+ /// Notify the appropriate <callback> in the context of the <eh>
+ /// associated with <handle> that a particular event has occurred.
+ virtual void notify_handle (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Handle_Set &,
+ ACE_Event_Handler *eh,
+ ACE_EH_PTMF callback);
+
+ /// Enqueue ourselves into the list of waiting threads at the
+ /// appropriate point specified by <requeue_position_>.
+ virtual void renew (void);
+
+ /// Synchronization token for the MT_SAFE ACE_Select_Reactor.
+ ACE_SELECT_REACTOR_TOKEN token_;
+
+ /// Adapter used to return internal lock to outside world.
+ ACE_Lock_Adapter<ACE_SELECT_REACTOR_TOKEN> lock_adapter_;
+
+ /// Release the token lock when a Win32 structured exception occurs.
+ int release_token (void);
+
+ /// Stops the VC++ compiler from bitching about exceptions and destructors
+ int handle_events_i (ACE_Time_Value *max_wait_time = 0);
+
+ /// This flag is used to keep track of whether we are actively handling
+ /// events or not.
+ sig_atomic_t deactivated_;
+
+ /**
+ * If 0 then the Reactor will not mask the signals during the event
+ * dispatching. This is useful for applications that do not
+ * register any signal handlers and want to reduce the overhead
+ * introduce by the kernel level locks required to change the mask.
+ */
+ int mask_signals_;
+
+private:
+ /// Deny access since member-wise won't work...
+ ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor_T (const ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN> &operator= (const ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN> &) )
+};
+
+// @@ The latest version of SunCC can't grok the code if we put inline
+// function here. Therefore, we temporarily disable the code here.
+// We shall turn this back on once we know the problem gets fixed.
+#if 0 // defined (__ACE_INLINE__)
+#include "ace/Select_Reactor_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Select_Reactor_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Select_Reactor_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_SELECT_REACTOR_T_H */
diff --git a/ace/Demux/Select_Reactor_T.i b/ace/Demux/Select_Reactor_T.i
new file mode 100644
index 00000000000..c3450e333ad
--- /dev/null
+++ b/ace/Demux/Select_Reactor_T.i
@@ -0,0 +1,241 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Reactor.h"
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handler (ACE_Event_Handler *h)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::resume_handler");
+ return this->resume_handler (h->get_handle ());
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handler (const ACE_Handle_Set &handles)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::resume_handler");
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->resume_i (h) == -1)
+ return -1;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handler (ACE_Event_Handler *h)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::suspend_handler");
+ return this->suspend_handler (h->get_handle ());
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handler (const ACE_Handle_Set &handles)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::suspend_handler");
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->suspend_i (h) == -1)
+ return -1;
+
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **old_sh,
+ ACE_Sig_Action *old_disp)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
+ return this->signal_handler_->register_handler (signum,
+ new_sh, new_disp,
+ old_sh, old_disp);
+}
+
+#if defined (ACE_WIN32)
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle)
+{
+ // Don't have an implementation for this yet...
+ ACE_UNUSED_ARG (event_handler);
+ ACE_UNUSED_ARG (event_handle);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+#endif /* ACE_WIN32 */
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // Don't have an implementation for this yet...
+ ACE_UNUSED_ARG (event_handle);
+ ACE_UNUSED_ARG (io_handle);
+ ACE_UNUSED_ARG (event_handler);
+ ACE_UNUSED_ARG (mask);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler (int signum, ACE_Event_Handler **handler)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::handler");
+ return this->handler_i (signum, handler);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int sigkey)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
+ return this->signal_handler_->remove_handler (signum, new_disp, old_disp, sigkey);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::uses_event_associations (void)
+{
+ // Since the Select_Reactor does not do any event associations, this
+ // function always return 0.
+ return 0;
+}
+
+// = The remaining methods in this file must be called with locks
+// held. Note the queue handles its own locking.
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::cancel_timer");
+ if (this->timer_queue_ != 0)
+ return this->timer_queue_->cancel (handler, dont_call_handle_close);
+ else
+ return 0;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::cancel_timer");
+ return this->timer_queue_->cancel (timer_id,
+ arg,
+ dont_call_handle_close);
+}
+
+// Performs operations on the "ready" bits.
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ready_ops (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::ready_ops");
+ return this->ready_ops (handler->get_handle (), mask, ops);
+}
+
+// Performs operations on the "dispatch" masks.
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::mask_ops (ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::mask_ops");
+ return this->mask_ops (handler->get_handle (), mask, ops);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::schedule_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::schedule_wakeup");
+ return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::ADD_MASK);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_wakeup (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::cancel_wakeup");
+ return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::CLR_MASK);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::schedule_wakeup");
+ return this->mask_ops (handle, mask, ACE_Reactor::ADD_MASK);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::cancel_wakeup");
+ return this->mask_ops (handle, mask, ACE_Reactor::CLR_MASK);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ ACE_Lock &
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::lock (void)
+{
+ ACE_TRACE ("ACE_Select_Reactor_T::lock");
+ return this->lock_adapter_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::wakeup_all_threads (void)
+{
+ // Send a notification, but don't block if there's no one to receive
+ // it.
+ this->notify (0, ACE_Event_Handler::NULL_MASK, (ACE_Time_Value *) &ACE_Time_Value::zero);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::alertable_handle_events (ACE_Time_Value *max_wait_time)
+{
+ return this->handle_events (max_wait_time);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::alertable_handle_events (ACE_Time_Value &max_wait_time)
+{
+ return this->handle_events (max_wait_time);
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ int
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::deactivated (void)
+{
+ return this->deactivated_;
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ void
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::deactivate (int do_stop)
+{
+ this->deactivated_ = do_stop;
+ this->wakeup_all_threads ();
+}
+
+template <class ACE_SELECT_REACTOR_TOKEN> /* ACE_INLINE */ size_t
+ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::size (void) const
+{
+ return this->handler_rep_.size ();
+}
diff --git a/ace/Demux/TkReactor.cpp b/ace/Demux/TkReactor.cpp
new file mode 100644
index 00000000000..78ca60e2741
--- /dev/null
+++ b/ace/Demux/TkReactor.cpp
@@ -0,0 +1,439 @@
+#include "ace/Synch_T.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/TkReactor.h"
+
+ACE_RCSID(ace, TkReactor, "$Id$")
+
+#if defined (ACE_HAS_TK)
+
+ACE_ALLOC_HOOK_DEFINE (ACE_TkReactor)
+
+// Must be called with lock held
+ACE_TkReactor::ACE_TkReactor (size_t size,
+ int restart,
+ ACE_Sig_Handler *h)
+ : ACE_Select_Reactor (size, restart, h),
+ ids_ (0),
+ timeout_ (0)
+{
+ // When the ACE_Select_Reactor is constructed it creates the notify
+ // pipe and registers it with the register_handler_i() method. The
+ // TkReactor overloads this method BUT because the
+ // register_handler_i occurs when constructing the base class
+ // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
+ // is called not the TkReactor register_handler_i(). This means
+ // that the notify pipe is registered with the ACE_Select_Reactor
+ // event handling code not the TkReactor and so notfications don't
+ // work. To get around this we simply close and re-opened the
+ // notification handler in the constructor of the TkReactor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->close ();
+ this->notify_handler_->open (this, 0);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_TkReactor::~ACE_TkReactor (void)
+{
+ // Delete the remaining items in the linked list.
+
+ while (this->ids_)
+ {
+ ACE_TkReactorID *TkID = this->ids_->next_;
+ delete this->ids_;
+ this->ids_ = TkID;
+ }
+}
+
+// This is just the <wait_for_multiple_events> from ace/Reactor.cpp
+// but we use the Tk functions to wait for an event, not <select>
+
+int
+ACE_TkReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_TkReactor::wait_for_multiple_events");
+ int nfound;
+
+ do
+ {
+ max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
+
+ size_t width = this->handler_rep_.max_handlep1 ();
+ handle_set.rd_mask_ = this->wait_set_.rd_mask_;
+ handle_set.wr_mask_ = this->wait_set_.wr_mask_;
+ handle_set.ex_mask_ = this->wait_set_.ex_mask_;
+ nfound = TkWaitForMultipleEvents (width,
+ handle_set,
+ max_wait_time);
+
+ } while (nfound == -1 && this->handle_error () > 0);
+
+ if (nfound > 0)
+ {
+#if !defined (ACE_WIN32)
+ handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_WIN32 */
+ }
+ return nfound; // Timed out or input available
+}
+
+void
+ACE_TkReactor::TimerCallbackProc (ClientData cd)
+{
+ ACE_TkReactor *self = (ACE_TkReactor *) cd;
+ self->timeout_ = 0;
+
+ // Deal with any timer events
+ ACE_Select_Reactor_Handle_Set handle_set;
+ self->dispatch (0, handle_set);
+ self->reset_timeout ();
+}
+
+/**
+ * @todo the unused mask argument is probably quite useful, but we
+ * ignore it, why? In fact the following comment probably
+ * relates to that:
+ * This could be made shorter if we know which *kind* of event
+ * we were about to get. Here we use <select> to find out which
+ * one might be available.
+ */
+void
+ACE_TkReactor::InputCallbackProc (ClientData cd,
+ int /* mask */)
+{
+ ACE_TkReactor_Input_Callback *callback = (ACE_TkReactor_Input_Callback *) cd;
+ ACE_TkReactor *self = callback->reactor_;
+ ACE_HANDLE handle = callback->handle_;
+
+ // my copy isn't const.
+ ACE_Time_Value zero = ACE_Time_Value::zero;
+
+ ACE_Select_Reactor_Handle_Set wait_set;
+
+ // Deal with one file event.
+
+ // - read which kind of event
+ if (self->wait_set_.rd_mask_.is_set (handle))
+ wait_set.rd_mask_.set_bit (handle);
+ if (self->wait_set_.wr_mask_.is_set (handle))
+ wait_set.wr_mask_.set_bit (handle);
+ if (self->wait_set_.ex_mask_.is_set (handle))
+ wait_set.ex_mask_.set_bit (handle);
+
+ int result = ACE_OS::select (handle + 1,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_, &zero);
+
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ // - Use only that one file event (removes events for other files).
+ if (result > 0)
+ {
+ if (wait_set.rd_mask_.is_set (handle))
+ dispatch_set.rd_mask_.set_bit (handle);
+ if (wait_set.wr_mask_.is_set (handle))
+ dispatch_set.wr_mask_.set_bit (handle);
+ if (wait_set.ex_mask_.is_set (handle))
+ dispatch_set.ex_mask_.set_bit (handle);
+
+ self->dispatch (1, dispatch_set);
+ }
+}
+
+int
+ACE_TkReactor::TkWaitForMultipleEvents (int width,
+ ACE_Select_Reactor_Handle_Set &wait_set,
+ ACE_Time_Value *)
+{
+ // Check to make sure our handle's are all usable.
+ ACE_Select_Reactor_Handle_Set temp_set = wait_set;
+
+ if (ACE_OS::select (width,
+ temp_set.rd_mask_,
+ temp_set.wr_mask_,
+ temp_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
+ return -1; // Bad file arguments...
+
+ // Instead of waiting using <select>, just use the Tk mechanism to
+ // wait for a single event.
+
+ // Wait for something to happen.
+ ::Tcl_DoOneEvent (0);
+
+ // Reset the width, in case it changed during the upcalls.
+ width = this->handler_rep_.max_handlep1 ();
+
+ // Now actually read the result needed by the <Select_Reactor> using
+ // <select>.
+ return ACE_OS::select (width,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero);
+}
+
+int
+ACE_TkReactor::register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_TkReactor::register_handler_i");
+
+ int result = ACE_Select_Reactor::register_handler_i (handle,
+ handler, mask);
+ if (result == -1)
+ return -1;
+
+ int condition = 0;
+
+#if !defined ACE_WIN32
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, TK_READABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, TK_WRITABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (condition, TK_EXCEPTION);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, TK_READABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
+ ACE_SET_BITS (condition, TK_READABLE); // connected, you may write
+ ACE_SET_BITS (condition, TK_WRITABLE); // connected, you have data/err
+ }
+#else
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, TK_READABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, TK_WRITABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_NOTSUP_RETURN(-1);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, TK_READABLE);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
+ ACE_SET_BITS (condition, TK_READABLE); // connected, you may write
+ ACE_SET_BITS (condition, TK_WRITABLE); // connected, you have data/err
+ }
+#endif /* !ACE_WIN32 */
+
+ if (condition != 0)
+ {
+ ACE_TkReactorID *TkID = this->ids_;
+
+ while(TkID)
+ {
+ if (TkID->handle_ == handle)
+ {
+ ::Tk_DeleteFileHandler (TkID->handle_);
+
+ ACE_TkReactor_Input_Callback *callback;
+ ACE_NEW_RETURN (callback,
+ ACE_TkReactor_Input_Callback,
+ -1);
+ callback->reactor_ = this;
+ callback->handle_ = handle;
+ ::Tk_CreateFileHandler ((int) handle,
+ condition,
+ InputCallbackProc,
+ (ClientData) callback);
+ return 0;
+ }
+ else
+ TkID = TkID->next_;
+ }
+
+ ACE_NEW_RETURN (TkID,
+ ACE_TkReactorID,
+ -1);
+ TkID->next_ = this->ids_;
+ TkID->handle_ = handle;
+ ACE_TkReactor_Input_Callback *callback;
+ ACE_NEW_RETURN (callback,
+ ACE_TkReactor_Input_Callback,
+ -1);
+ callback->reactor_ = this;
+ callback->handle_ = handle;
+
+ ::Tk_CreateFileHandler ((int) handle,
+ condition,
+ InputCallbackProc,
+ (ClientData) callback);
+ this->ids_ = TkID;
+ }
+ return 0;
+}
+
+int
+ACE_TkReactor::register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::register_handler_i (handles,
+ handler,
+ mask);
+}
+
+int
+ACE_TkReactor::remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_TkReactor::remove_handler_i");
+
+ // In the registration phase we registered first with
+ // ACE_Select_Reactor and then with X. Now we are now doing things
+ // in reverse order.
+
+ // First clean up the corresponding X11Input.
+ this->remove_TkFileHandler (handle);
+
+ // Now let the reactor do its work.
+ return ACE_Select_Reactor::remove_handler_i (handle,
+ mask);
+}
+
+void
+ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
+
+ ACE_TkReactorID *TkID = this->ids_;
+
+ if (TkID)
+ {
+ if (TkID->handle_ == handle)
+ {
+ ::Tk_DeleteFileHandler (TkID->handle_);
+ this->ids_ = TkID->next_;
+ delete TkID;
+ return;
+ }
+
+ ACE_TkReactorID *NextID = TkID->next_;
+
+ while (NextID)
+ {
+ if (NextID->handle_ == handle)
+ {
+ ::Tk_DeleteFileHandler (NextID->handle_);
+ TkID->next_ = NextID->next_;
+ delete NextID;
+ return;
+ }
+ else
+ {
+ TkID = NextID;
+ NextID = NextID->next_;
+ }
+ }
+ }
+}
+
+int
+ACE_TkReactor::remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::remove_handler_i (handles,
+ mask);
+}
+
+// The following functions ensure that there is an Tk timeout for the
+// first timeout in the Reactor's Timer_Queue.
+
+void
+ACE_TkReactor::reset_timeout (void)
+{
+ if (this->timeout_)
+ ::Tk_DeleteTimerHandler (this->timeout_);
+ timeout_ = 0;
+
+ ACE_Time_Value *max_wait_time =
+ this->timer_queue_->calculate_timeout (0);
+
+ if (max_wait_time)
+ timeout_ = ::Tk_CreateTimerHandler (max_wait_time->msec (),
+ TimerCallbackProc,
+ (ClientData) this);
+}
+
+int
+ACE_TkReactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_TkReactor::reset_timer_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ int result = ACE_Select_Reactor::timer_queue_->reset_interval
+ (timer_id,
+ interval);
+
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+long
+ACE_TkReactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_TkReactor::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ long result = ACE_Select_Reactor::schedule_timer (handler,
+ arg,
+ delay_time,
+ interval);
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+int
+ACE_TkReactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_TkReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (handler,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+int
+ACE_TkReactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_TkReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (timer_id,
+ arg,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+#endif /* ACE_HAS_TK */
diff --git a/ace/Demux/TkReactor.h b/ace/Demux/TkReactor.h
new file mode 100644
index 00000000000..7aca8465274
--- /dev/null
+++ b/ace/Demux/TkReactor.h
@@ -0,0 +1,130 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file TkReactor.h
+ *
+ * $Id$
+ *
+ * @author Nagarajan Surendran <naga@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_TKREACTOR_H
+#define ACE_TKREACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor.h"
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TK)
+#include <tk.h>
+
+/**
+ * @class ACE_TkReactorID
+ *
+ * @brief This little class is necessary due to the way that Microsoft
+ * implements sockets to be pointers rather than indices.
+ */
+class ACE_Export ACE_TkReactorID
+{
+public:
+ /// Underlying handle.
+ ACE_HANDLE handle_;
+
+ /// Pointer to next node in the linked list.
+ ACE_TkReactorID *next_;
+};
+
+class ACE_TkReactor;
+
+class ACE_Export ACE_TkReactor_Input_Callback
+{
+public:
+ ACE_TkReactor *reactor_;
+ ACE_HANDLE handle_;
+};
+
+/**
+ * @class ACE_TkReactor
+ *
+ * @brief An object-oriented event demultiplexor and event handler
+ * dispatcher that uses the Tk functions.
+ */
+class ACE_Export ACE_TkReactor : public ACE_Select_Reactor
+{
+public:
+ // = Initialization and termination methods.
+ ACE_TkReactor (size_t size = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0);
+
+ virtual ~ACE_TkReactor (void);
+
+ // = Timer operations.
+ virtual long schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval);
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+ virtual int cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close = 1);
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+protected:
+ // = Register timers/handles with Tk.
+ /// Register a single <handler>.
+ virtual int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register a set of <handlers>.
+ virtual int register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Remove the <handler> associated with this <handle>.
+ virtual int remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// Remove a set of <handles>.
+ virtual int remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask);
+
+ /// Removes an Tk FileHandler.
+ virtual void remove_TkFileHandler (ACE_HANDLE handle);
+
+ /// Wait for events to occur.
+ virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+ ///Wait for Tk events to occur.
+ virtual int TkWaitForMultipleEvents (int,
+ ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+ ACE_TkReactorID *ids_;
+ Tk_TimerToken timeout_;
+
+private:
+ /// This method ensures there's a Tk timeout for the first timeout in
+ /// the Reactor's Timer_Queue.
+ void reset_timeout (void);
+
+ // = Integrate with the X callback function mechanism.
+ static void TimerCallbackProc (ClientData cd);
+ static void InputCallbackProc (ClientData cd,int mask);
+
+ /// Deny access since member-wise won't work...
+ ACE_TkReactor (const ACE_TkReactor &);
+ ACE_TkReactor &operator = (const ACE_TkReactor &);
+};
+
+#endif /* ACE_HAS_TK */
+#include "ace/post.h"
+#endif /* ACE_TK_REACTOR_H */
diff --git a/ace/Demux/WFMO_Reactor.cpp b/ace/Demux/WFMO_Reactor.cpp
new file mode 100644
index 00000000000..b6a41d2e9d3
--- /dev/null
+++ b/ace/Demux/WFMO_Reactor.cpp
@@ -0,0 +1,2563 @@
+// $Id$
+
+#include "ace/WFMO_Reactor.h"
+
+#include "ace/Handle_Set.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Thread.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/WFMO_Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, WFMO_Reactor, "$Id$")
+
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+#include "ace/Auto_Ptr.h"
+
+ACE_WFMO_Reactor_Handler_Repository::ACE_WFMO_Reactor_Handler_Repository (ACE_WFMO_Reactor &wfmo_reactor)
+ : wfmo_reactor_ (wfmo_reactor)
+{
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::open (size_t size)
+{
+ if (size > MAXIMUM_WAIT_OBJECTS)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%d exceeds MAXIMUM_WAIT_OBJECTS (%d)\n"),
+ size,
+ MAXIMUM_WAIT_OBJECTS),
+ -1);
+
+ // Dynamic allocation
+ ACE_NEW_RETURN (this->current_handles_,
+ ACE_HANDLE[size],
+ -1);
+ ACE_NEW_RETURN (this->current_info_,
+ Current_Info[size],
+ -1);
+ ACE_NEW_RETURN (this->current_suspended_info_,
+ Suspended_Info[size],
+ -1);
+ ACE_NEW_RETURN (this->to_be_added_info_,
+ To_Be_Added_Info[size],
+ -1);
+
+ // Initialization
+ this->max_size_ = size;
+ this->max_handlep1_ = 0;
+ this->suspended_handles_ = 0;
+ this->handles_to_be_added_ = 0;
+ this->handles_to_be_deleted_ = 0;
+ this->handles_to_be_suspended_ = 0;
+ this->handles_to_be_resumed_ = 0;
+
+ for (size_t i = 0; i < size; i++)
+ this->current_handles_[i] = ACE_INVALID_HANDLE;
+
+ return 0;
+}
+
+ACE_WFMO_Reactor_Handler_Repository::~ACE_WFMO_Reactor_Handler_Repository (void)
+{
+ // Free up dynamically allocated space
+ delete [] this->current_handles_;
+ delete [] this->current_info_;
+ delete [] this->current_suspended_info_;
+ delete [] this->to_be_added_info_;
+}
+
+ACE_Reactor_Mask
+ACE_WFMO_Reactor_Handler_Repository::bit_ops (long &existing_masks,
+ ACE_Reactor_Mask change_masks,
+ int operation)
+{
+ // Find the old reactor masks. This automatically does the work of
+ // the GET_MASK operation.
+
+ ACE_Reactor_Mask old_masks = ACE_Event_Handler::NULL_MASK;
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_READ)
+ || ACE_BIT_ENABLED (existing_masks, FD_CLOSE))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::READ_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_WRITE))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::WRITE_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_OOB))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::EXCEPT_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_ACCEPT))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::ACCEPT_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_CONNECT))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::CONNECT_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_QOS))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::QOS_MASK);
+
+ if (ACE_BIT_ENABLED (existing_masks, FD_GROUP_QOS))
+ ACE_SET_BITS (old_masks, ACE_Event_Handler::GROUP_QOS_MASK);
+
+ switch (operation)
+ {
+ case ACE_Reactor::CLR_MASK:
+ // For the CLR_MASK operation, clear only the specific masks.
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::READ_MASK))
+ {
+ ACE_CLR_BITS (existing_masks, FD_READ);
+ ACE_CLR_BITS (existing_masks, FD_CLOSE);
+ }
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::WRITE_MASK))
+ ACE_CLR_BITS (existing_masks, FD_WRITE);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_CLR_BITS (existing_masks, FD_OOB);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_CLR_BITS (existing_masks, FD_ACCEPT);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::CONNECT_MASK))
+ ACE_CLR_BITS (existing_masks, FD_CONNECT);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::QOS_MASK))
+ ACE_CLR_BITS (existing_masks, FD_QOS);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::GROUP_QOS_MASK))
+ ACE_CLR_BITS (existing_masks, FD_GROUP_QOS);
+
+ break;
+
+ case ACE_Reactor::SET_MASK:
+ // If the operation is a set, first reset any existing masks
+
+ existing_masks = 0;
+ /* FALLTHRU */
+
+ case ACE_Reactor::ADD_MASK:
+ // For the ADD_MASK and the SET_MASK operation, add only the
+ // specific masks.
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::READ_MASK))
+ {
+ ACE_SET_BITS (existing_masks, FD_READ);
+ ACE_SET_BITS (existing_masks, FD_CLOSE);
+ }
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (existing_masks, FD_WRITE);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (existing_masks, FD_OOB);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (existing_masks, FD_ACCEPT);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::CONNECT_MASK))
+ ACE_SET_BITS (existing_masks, FD_CONNECT);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::QOS_MASK))
+ ACE_SET_BITS (existing_masks, FD_QOS);
+
+ if (ACE_BIT_ENABLED (change_masks, ACE_Event_Handler::GROUP_QOS_MASK))
+ ACE_SET_BITS (existing_masks, FD_GROUP_QOS);
+
+ break;
+
+ case ACE_Reactor::GET_MASK:
+
+ // The work for this operation is done in all cases at the
+ // begining of the function.
+
+ ACE_UNUSED_ARG (change_masks);
+
+ break;
+ }
+
+ return old_masks;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::unbind_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int &changes_required)
+{
+ int error = 0;
+
+ // Remember this value; only if it changes do we need to wakeup
+ // the other threads
+ size_t original_handle_count = this->handles_to_be_deleted_;
+ int result = 0;
+ size_t i;
+
+ // Go through all the handles looking for <handle>. Even if we find
+ // it, we continue through the rest of the list since <handle> could
+ // appear multiple times. All handles are checked.
+
+ // First check the current entries
+ for (i = 0; i < this->max_handlep1_ && error == 0; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->current_handles_[i] == handle
+ || this->current_info_[i].io_handle_ == handle)
+ && // Make sure that it is not already marked for deleted
+ !this->current_info_[i].delete_entry_)
+ {
+ result = this->remove_handler_i (i,
+ mask);
+ if (result == -1)
+ error = 1;
+ }
+
+ // Then check the suspended entries
+ for (i = 0; i < this->suspended_handles_ && error == 0; i++)
+ // Since the handle can either be the event or the I/O handle, we
+ // have to check both
+ if ((this->current_suspended_info_[i].io_handle_ == handle
+ || this->current_suspended_info_[i].event_handle_ == handle)
+ &&
+ // Make sure that it is not already marked for deleted
+ !this->current_suspended_info_[i].delete_entry_)
+ {
+ result = this->remove_suspended_handler_i (i,
+ mask);
+ if (result == -1)
+ error = 1;
+ }
+
+ // Then check the to_be_added entries
+ for (i = 0; i < this->handles_to_be_added_ && error == 0; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->to_be_added_info_[i].io_handle_ == handle
+ || this->to_be_added_info_[i].event_handle_ == handle)
+ &&
+ // Make sure that it is not already marked for deleted
+ !this->to_be_added_info_[i].delete_entry_)
+ {
+ result = this->remove_to_be_added_handler_i (i,
+ mask);
+ if (result == -1)
+ error = 1;
+ }
+
+ // Only if the number of handlers to be deleted changes do we need
+ // to wakeup the other threads
+ if (original_handle_count < this->handles_to_be_deleted_)
+ changes_required = 1;
+
+ return error ? -1 : 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::remove_handler_i (size_t slot,
+ ACE_Reactor_Mask to_be_removed_masks)
+{
+ // I/O entries
+ if (this->current_info_[slot].io_entry_)
+ {
+ // See if there are other events that the <Event_Handler> is
+ // interested in
+ this->bit_ops (this->current_info_[slot].network_events_,
+ to_be_removed_masks,
+ ACE_Reactor::CLR_MASK);
+
+ // Disassociate/Reassociate the event from/with the I/O handle.
+ // This will depend on the value of remaining set of network
+ // events that the <event_handler> is interested in. I don't
+ // think we can do anything about errors here, so I will not
+ // check this.
+ ::WSAEventSelect ((SOCKET) this->current_info_[slot].io_handle_,
+ this->current_handles_[slot],
+ this->current_info_[slot].network_events_);
+ }
+ // Normal event entries.
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL))
+ // Preserve DONT_CALL
+ to_be_removed_masks = ACE_Event_Handler::DONT_CALL;
+ else
+ // Make sure that the <to_be_removed_masks> is the NULL_MASK
+ to_be_removed_masks = ACE_Event_Handler::NULL_MASK;
+
+ // If this event was marked for suspension, undo the suspension flag
+ // and reduce the to be suspended count.
+ if (this->current_info_[slot].suspend_entry_)
+ {
+ // Undo suspension
+ this->current_info_[slot].suspend_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_suspended_--;
+ }
+
+ // If there are no more events that the <Event_Handler> is
+ // interested in, or this is a non-I/O entry, schedule the
+ // <Event_Handler> for removal
+ if (this->current_info_[slot].network_events_ == 0)
+ {
+ // Mark to be deleted
+ this->current_info_[slot].delete_entry_ = 1;
+ // Remember the mask
+ this->current_info_[slot].close_masks_ = to_be_removed_masks;
+ // Increment the handle count
+ this->handles_to_be_deleted_++;
+ }
+
+ // Since it is not a complete removal, we'll call handle_close
+ // for all the masks that were removed. This does not change
+ // the internal state of the reactor.
+ //
+ // Note: this condition only applies to I/O entries
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ ACE_HANDLE handle = this->current_info_[slot].io_handle_;
+ this->current_info_[slot].event_handler_->handle_close (handle,
+ to_be_removed_masks);
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::remove_suspended_handler_i (size_t slot,
+ ACE_Reactor_Mask to_be_removed_masks)
+{
+ // I/O entries
+ if (this->current_suspended_info_[slot].io_entry_)
+ {
+ // See if there are other events that the <Event_Handler> is
+ // interested in
+ this->bit_ops (this->current_suspended_info_[slot].network_events_,
+ to_be_removed_masks,
+ ACE_Reactor::CLR_MASK);
+
+ // Disassociate/Reassociate the event from/with the I/O handle.
+ // This will depend on the value of remaining set of network
+ // events that the <event_handler> is interested in. I don't
+ // think we can do anything about errors here, so I will not
+ // check this.
+ ::WSAEventSelect ((SOCKET) this->current_suspended_info_[slot].io_handle_,
+ this->current_suspended_info_[slot].event_handle_,
+ this->current_suspended_info_[slot].network_events_);
+ }
+ // Normal event entries.
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL))
+ // Preserve DONT_CALL
+ to_be_removed_masks = ACE_Event_Handler::DONT_CALL;
+ else
+ // Make sure that the <to_be_removed_masks> is the NULL_MASK
+ to_be_removed_masks = ACE_Event_Handler::NULL_MASK;
+
+ // If this event was marked for resumption, undo the resumption flag
+ // and reduce the to be resumed count.
+ if (this->current_suspended_info_[slot].resume_entry_)
+ {
+ // Undo resumption
+ this->current_suspended_info_[slot].resume_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_resumed_--;
+ }
+
+ // If there are no more events that the <Event_Handler> is
+ // interested in, or this is a non-I/O entry, schedule the
+ // <Event_Handler> for removal
+ if (this->current_suspended_info_[slot].network_events_ == 0)
+ {
+ // Mark to be deleted
+ this->current_suspended_info_[slot].delete_entry_ = 1;
+ // Remember the mask
+ this->current_suspended_info_[slot].close_masks_ = to_be_removed_masks;
+ // Increment the handle count
+ this->handles_to_be_deleted_++;
+ }
+ // Since it is not a complete removal, we'll call handle_close for
+ // all the masks that were removed. This does not change the
+ // internal state of the reactor.
+ //
+ // Note: this condition only applies to I/O entries
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ ACE_HANDLE handle = this->current_suspended_info_[slot].io_handle_;
+ this->current_suspended_info_[slot].event_handler_->handle_close (handle,
+ to_be_removed_masks);
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::remove_to_be_added_handler_i (size_t slot,
+ ACE_Reactor_Mask to_be_removed_masks)
+{
+ // I/O entries
+ if (this->to_be_added_info_[slot].io_entry_)
+ {
+ // See if there are other events that the <Event_Handler> is
+ // interested in
+ this->bit_ops (this->to_be_added_info_[slot].network_events_,
+ to_be_removed_masks,
+ ACE_Reactor::CLR_MASK);
+
+ // Disassociate/Reassociate the event from/with the I/O handle.
+ // This will depend on the value of remaining set of network
+ // events that the <event_handler> is interested in. I don't
+ // think we can do anything about errors here, so I will not
+ // check this.
+ ::WSAEventSelect ((SOCKET) this->to_be_added_info_[slot].io_handle_,
+ this->to_be_added_info_[slot].event_handle_,
+ this->to_be_added_info_[slot].network_events_);
+ }
+ // Normal event entries.
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL))
+ // Preserve DONT_CALL
+ to_be_removed_masks = ACE_Event_Handler::DONT_CALL;
+ else
+ // Make sure that the <to_be_removed_masks> is the NULL_MASK
+ to_be_removed_masks = ACE_Event_Handler::NULL_MASK;
+
+ // If this event was marked for suspension, undo the suspension flag
+ // and reduce the to be suspended count.
+ if (this->to_be_added_info_[slot].suspend_entry_)
+ {
+ // Undo suspension
+ this->to_be_added_info_[slot].suspend_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_suspended_--;
+ }
+
+ // If there are no more events that the <Event_Handler> is
+ // interested in, or this is a non-I/O entry, schedule the
+ // <Event_Handler> for removal
+ if (this->to_be_added_info_[slot].network_events_ == 0)
+ {
+ // Mark to be deleted
+ this->to_be_added_info_[slot].delete_entry_ = 1;
+ // Remember the mask
+ this->to_be_added_info_[slot].close_masks_ = to_be_removed_masks;
+ // Increment the handle count
+ this->handles_to_be_deleted_++;
+ }
+ // Since it is not a complete removal, we'll call handle_close
+ // for all the masks that were removed. This does not change
+ // the internal state of the reactor.
+ //
+ // Note: this condition only applies to I/O entries
+ else if (ACE_BIT_ENABLED (to_be_removed_masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ ACE_HANDLE handle = this->to_be_added_info_[slot].io_handle_;
+ this->to_be_added_info_[slot].event_handler_->handle_close (handle,
+ to_be_removed_masks);
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::suspend_handler_i (ACE_HANDLE handle,
+ int &changes_required)
+{
+ size_t i = 0;
+
+ // Go through all the handles looking for <handle>. Even if we find
+ // it, we continue through the rest of the list since <handle> could
+ // appear multiple times. All handles are checked.
+
+ // Check the current entries first.
+ for (i = 0; i < this->max_handlep1_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->current_handles_[i] == handle ||
+ this->current_info_[i].io_handle_ == handle) &&
+ // Make sure that it is not already marked for suspension
+ !this->current_info_[i].suspend_entry_)
+ {
+ // Mark to be suspended
+ this->current_info_[i].suspend_entry_ = 1;
+ // Increment the handle count
+ this->handles_to_be_suspended_++;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ // Then check the suspended entries.
+ for (i = 0; i < this->suspended_handles_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->current_suspended_info_[i].event_handle_ == handle ||
+ this->current_suspended_info_[i].io_handle_ == handle) &&
+ // Make sure that the resumption is not already undone
+ this->current_suspended_info_[i].resume_entry_)
+ {
+ // Undo resumption
+ this->current_suspended_info_[i].resume_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_resumed_--;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ // Then check the to_be_added entries.
+ for (i = 0; i < this->handles_to_be_added_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->to_be_added_info_[i].io_handle_ == handle ||
+ this->to_be_added_info_[i].event_handle_ == handle) &&
+ // Make sure that it is not already marked for suspension
+ !this->to_be_added_info_[i].suspend_entry_)
+ {
+ // Mark to be suspended
+ this->to_be_added_info_[i].suspend_entry_ = 1;
+ // Increment the handle count
+ this->handles_to_be_suspended_++;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::resume_handler_i (ACE_HANDLE handle,
+ int &changes_required)
+{
+ size_t i = 0;
+
+ // Go through all the handles looking for <handle>. Even if we find
+ // it, we continue through the rest of the list since <handle> could
+ // appear multiple times. All handles are checked.
+
+ // Check the current entries first.
+ for (i = 0; i < this->max_handlep1_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->current_handles_[i] == handle ||
+ this->current_info_[i].io_handle_ == handle) &&
+ // Make sure that the suspension is not already undone
+ this->current_info_[i].suspend_entry_)
+ {
+ // Undo suspension
+ this->current_info_[i].suspend_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_suspended_--;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ // Then check the suspended entries.
+ for (i = 0; i < this->suspended_handles_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->current_suspended_info_[i].event_handle_ == handle ||
+ this->current_suspended_info_[i].io_handle_ == handle) &&
+ // Make sure that it is not already marked for resumption
+ !this->current_suspended_info_[i].resume_entry_)
+ {
+ // Mark to be resumed
+ this->current_suspended_info_[i].resume_entry_ = 1;
+ // Increment the handle count
+ this->handles_to_be_resumed_++;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ // Then check the to_be_added entries.
+ for (i = 0; i < this->handles_to_be_added_; i++)
+ // Since the handle can either be the event or the I/O handle,
+ // we have to check both
+ if ((this->to_be_added_info_[i].io_handle_ == handle ||
+ this->to_be_added_info_[i].event_handle_ == handle) &&
+ // Make sure that the suspension is not already undone
+ this->to_be_added_info_[i].suspend_entry_)
+ {
+ // Undo suspension
+ this->to_be_added_info_[i].suspend_entry_ = 0;
+ // Decrement the handle count
+ this->handles_to_be_suspended_--;
+ // Changes will be required
+ changes_required = 1;
+ }
+
+ return 0;
+}
+
+void
+ACE_WFMO_Reactor_Handler_Repository::unbind_all (void)
+{
+ {
+ ACE_GUARD (ACE_Process_Mutex, ace_mon, this->wfmo_reactor_.lock_);
+
+ int dummy;
+ size_t i;
+
+ // Remove all the current handlers
+ for (i = 0; i < this->max_handlep1_; i++)
+ this->unbind_i (this->current_handles_[i],
+ ACE_Event_Handler::ALL_EVENTS_MASK,
+ dummy);
+
+ // Remove all the suspended handlers
+ for (i = 0; i < this->suspended_handles_; i++)
+ this->unbind_i (this->current_suspended_info_[i].event_handle_,
+ ACE_Event_Handler::ALL_EVENTS_MASK,
+ dummy);
+
+ // Remove all the to_be_added handlers
+ for (i = 0; i < this->handles_to_be_added_; i++)
+ this->unbind_i (this->to_be_added_info_[i].event_handle_,
+ ACE_Event_Handler::ALL_EVENTS_MASK,
+ dummy);
+
+ }
+
+ // The guard is released here
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wfmo_reactor_.wakeup_all_threads ();
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::bind_i (int io_entry,
+ ACE_Event_Handler *event_handler,
+ long network_events,
+ ACE_HANDLE io_handle,
+ ACE_HANDLE event_handle,
+ int delete_event)
+{
+ // Make sure that the <handle> is valid
+ if (event_handle == ACE_INVALID_HANDLE)
+ event_handle = event_handler->get_handle ();
+ if (this->invalid_handle (event_handle))
+ return -1;
+
+ size_t current_size = this->max_handlep1_ +
+ this->handles_to_be_added_ -
+ this->handles_to_be_deleted_ +
+ this->suspended_handles_;
+
+ // Make sure that there's room in the table.
+ if (current_size < this->max_size_)
+ {
+ // Cache this set into the <to_be_added_info_>, till we come
+ // around to actually adding this to the <current_info_>
+ this->to_be_added_info_[this->handles_to_be_added_].set (event_handle,
+ io_entry,
+ event_handler,
+ io_handle,
+ network_events,
+ delete_event);
+
+ this->handles_to_be_added_++;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wfmo_reactor_.wakeup_all_threads ();
+ }
+ else
+ {
+ errno = EMFILE; // File descriptor table is full (better than nothing)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::make_changes_in_current_infos (void)
+{
+ // Go through the entire valid array and check for all handles that
+ // have been schedule for deletion
+ if (this->handles_to_be_deleted_ > 0 || this->handles_to_be_suspended_ > 0)
+ {
+ // This will help us in keeping track of the last valid slot in the
+ // handle arrays
+ int last_valid_slot = this->max_handlep1_ - 1;
+
+ for (int i = last_valid_slot; i >= 0; i--)
+ {
+ // This stuff is necessary here, since we should not make
+ // the upcall until all the internal data structures have
+ // been updated. This is to protect against upcalls that
+ // try to deregister again.
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+ ACE_Reactor_Mask masks = ACE_Event_Handler::NULL_MASK;
+ ACE_Event_Handler *event_handler = 0;
+
+ // See if this entry is scheduled for deletion
+ if (this->current_info_[i].delete_entry_)
+ {
+ // Calling the <handle_close> method here will ensure that we
+ // will only call it once per deregistering <Event_Handler>.
+ // This is essential in the case when the <Event_Handler> will
+ // do something like delete itself and we have multiple
+ // threads in WFMO_Reactor.
+ //
+ // Make sure that the DONT_CALL mask is not set
+ masks = this->current_info_[i].close_masks_;
+ if (ACE_BIT_ENABLED (masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ // Grab the correct handle depending on the type entry
+ if (this->current_info_[i].io_entry_)
+ handle = this->current_info_[i].io_handle_;
+ else
+ handle = this->current_handles_[i];
+
+ // Event handler
+ event_handler = this->current_info_[i].event_handler_;
+ }
+
+ // If <WFMO_Reactor> created the event, we need to clean it up
+ if (this->current_info_[i].delete_event_)
+ ACE_OS::event_destroy (&this->current_handles_[i]);
+
+ // Reduce count by one
+ this->handles_to_be_deleted_--;
+ }
+
+ // See if this entry is scheduled for suspension
+ else if (this->current_info_[i].suspend_entry_)
+ {
+ this->current_suspended_info_ [this->suspended_handles_].set (this->current_handles_[i],
+ this->current_info_[i]);
+ // Increase number of suspended handles
+ this->suspended_handles_++;
+
+ // Reduce count by one
+ this->handles_to_be_suspended_--;
+ }
+
+ // See if this entry is scheduled for deletion or suspension
+ // If so we need to clean up
+ if (this->current_info_[i].delete_entry_ || this->current_info_[i].suspend_entry_)
+ {
+ if (i == last_valid_slot)
+ // If this is the last handle in the set, no need to swap
+ // places. Simply remove it.
+ {
+ // Reset the info in this slot
+ this->current_info_[i].reset ();
+ this->current_handles_[i] = ACE_INVALID_HANDLE;
+ }
+ else
+ // Swap this handle with the last valid handle
+ {
+ // Struct copy
+ this->current_info_[i] = this->current_info_[last_valid_slot];
+ this->current_handles_[i] = this->current_handles_[last_valid_slot];
+ // Reset the info in the last slot
+ this->current_info_[last_valid_slot].reset ();
+ this->current_handles_[last_valid_slot] = ACE_INVALID_HANDLE;
+ }
+ // Reset the last valid slot and clean up the entry in the
+ // <to_be_deleted_set_>
+ last_valid_slot--;
+ }
+
+ // Now that all internal structures have been updated, make
+ // the upcall.
+ if (event_handler != 0)
+ event_handler->handle_close (handle, masks);
+ }
+ // Reset <this->max_handlep1_>
+ this->max_handlep1_ = last_valid_slot + 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::make_changes_in_suspension_infos (void)
+{
+ int i;
+
+ // Go through the <suspended_handle> array
+ if (this->handles_to_be_deleted_ > 0 || this->handles_to_be_resumed_ > 0)
+ {
+ int last_valid_slot = this->suspended_handles_ - 1;
+ for (i = last_valid_slot; i >= 0; i--)
+ {
+ // This stuff is necessary here, since we should not make
+ // the upcall until all the internal data structures have
+ // been updated. This is to protect against upcalls that
+ // try to deregister again.
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+ ACE_Reactor_Mask masks = ACE_Event_Handler::NULL_MASK;
+ ACE_Event_Handler *event_handler = 0;
+
+ // See if this entry is scheduled for deletion
+ if (this->current_suspended_info_[i].delete_entry_)
+ {
+ // Calling the <handle_close> method here will ensure that we
+ // will only call it once per deregistering <Event_Handler>.
+ // This is essential in the case when the <Event_Handler> will
+ // do something like delete itself and we have multiple
+ // threads in WFMO_Reactor.
+ //
+ // Make sure that the DONT_CALL mask is not set
+ masks = this->current_suspended_info_[i].close_masks_;
+ if (ACE_BIT_ENABLED (masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ // Grab the correct handle depending on the type entry
+ if (this->current_suspended_info_[i].io_entry_)
+ handle = this->current_suspended_info_[i].io_handle_;
+ else
+ handle = this->current_suspended_info_[i].event_handle_;
+
+ // Upcall
+ event_handler = this->current_suspended_info_[i].event_handler_;
+ }
+
+ // If <WFMO_Reactor> created the event, we need to clean it up
+ if (this->current_suspended_info_[i].delete_event_)
+ ACE_OS::event_destroy (&this->current_suspended_info_[i].event_handle_);
+
+ // Reduce count by one
+ this->handles_to_be_deleted_--;
+ }
+
+ else if (this->current_suspended_info_[i].resume_entry_)
+ {
+ // Add to the end of the current handles set
+ this->current_handles_[this->max_handlep1_] = this->current_suspended_info_[i].event_handle_;
+ // Struct copy
+ this->current_info_[this->max_handlep1_].set (this->current_suspended_info_[i]);
+ this->max_handlep1_++;
+
+ // Reduce count by one
+ this->handles_to_be_resumed_--;
+ }
+
+ if (this->current_suspended_info_[i].resume_entry_ ||
+ this->current_suspended_info_[i].delete_entry_)
+ {
+ // Is this the last entry
+ if (i == last_valid_slot)
+ // Reset the <suspended> arrays entries
+ this->current_suspended_info_[i].reset ();
+ else
+ {
+ // Struct copy
+ this->current_suspended_info_[i] = this->current_suspended_info_[last_valid_slot];
+ this->current_suspended_info_[last_valid_slot].reset ();
+ }
+ // Reduce the number of suspended handles
+ last_valid_slot--;
+ }
+
+ // Now that all internal structures have been updated, make
+ // the upcall.
+ if (event_handler != 0)
+ event_handler->handle_close (handle, masks);
+ }
+
+ // Reset <this->suspended_handles_>
+ this->suspended_handles_ = last_valid_slot + 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::make_changes_in_to_be_added_infos (void)
+{
+ int i;
+
+ // Go through the <to_be_added_*> arrays
+ for (i = 0; i < (int) this->handles_to_be_added_; i++)
+ {
+ // This stuff is necessary here, since we should not make
+ // the upcall until all the internal data structures have
+ // been updated. This is to protect against upcalls that
+ // try to deregister again.
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+ ACE_Reactor_Mask masks = ACE_Event_Handler::NULL_MASK;
+ ACE_Event_Handler *event_handler = 0;
+
+ // See if this entry is scheduled for deletion
+ if (this->to_be_added_info_[i].delete_entry_)
+ {
+ // Calling the <handle_close> method here will ensure that we
+ // will only call it once per deregistering <Event_Handler>.
+ // This is essential in the case when the <Event_Handler> will
+ // do something like delete itself and we have multiple
+ // threads in WFMO_Reactor.
+ //
+ // Make sure that the DONT_CALL mask is not set
+ masks = this->to_be_added_info_[i].close_masks_;
+ if (ACE_BIT_ENABLED (masks, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ // Grab the correct handle depending on the type entry
+ if (this->to_be_added_info_[i].io_entry_)
+ handle = this->to_be_added_info_[i].io_handle_;
+ else
+ handle = this->to_be_added_info_[i].event_handle_;
+
+ // Upcall
+ event_handler = this->to_be_added_info_[i].event_handler_;
+ }
+
+ // If <WFMO_Reactor> created the event, we need to clean it up
+ if (this->to_be_added_info_[i].delete_event_)
+ ACE_OS::event_destroy (&this->to_be_added_info_[i].event_handle_);
+
+ // Reduce count by one
+ this->handles_to_be_deleted_--;
+ }
+
+ // See if this entry is scheduled for suspension
+ else if (this->to_be_added_info_[i].suspend_entry_)
+ {
+ this->current_suspended_info_ [this->suspended_handles_].set (this->to_be_added_info_[i].event_handle_,
+ this->to_be_added_info_[i]);
+ // Increase number of suspended handles
+ this->suspended_handles_++;
+
+ // Reduce count by one
+ this->handles_to_be_suspended_--;
+ }
+
+ // If neither of the two flags are on, add to current
+ else
+ {
+ // Add to the end of the current handles set
+ this->current_handles_[this->max_handlep1_] = this->to_be_added_info_[i].event_handle_;
+ // Struct copy
+ this->current_info_[this->max_handlep1_].set (this->to_be_added_info_[i]);
+ this->max_handlep1_++;
+ }
+
+ // Reset the <to_be_added_info_>
+ this->to_be_added_info_[i].reset ();
+
+ // Now that all internal structures have been updated, make the
+ // upcall.
+ if (event_handler != 0)
+ event_handler->handle_close (handle, masks);
+ }
+
+ // Since all to be added handles have been taken care of, reset the
+ // counter
+ this->handles_to_be_added_ = 0;
+
+ return 0;
+}
+
+void
+ACE_WFMO_Reactor_Handler_Repository::dump (void) const
+{
+ size_t i = 0;
+
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Max size = %d\n"),
+ this->max_size_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Current info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\tSize = %d\n"),
+ this->max_handlep1_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\tHandles to be suspended = %d\n"),
+ this->handles_to_be_suspended_));
+
+ for (i = 0; i < this->max_handlep1_; i++)
+ this->current_info_[i].dump (this->current_handles_[i]);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("To-be-added info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\tSize = %d\n"),
+ this->handles_to_be_added_));
+
+ for (i = 0; i < this->handles_to_be_added_; i++)
+ this->to_be_added_info_[i].dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Suspended info table\n\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\tSize = %d\n"),
+ this->suspended_handles_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\tHandles to be resumed = %d\n"),
+ this->handles_to_be_resumed_));
+
+ for (i = 0; i < this->suspended_handles_; i++)
+ this->current_suspended_info_[i].dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Total handles to be deleted = %d\n"),
+ this->handles_to_be_deleted_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_END_DUMP));
+}
+
+/************************************************************/
+
+int
+ACE_WFMO_Reactor::work_pending (const ACE_Time_Value &)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_WFMO_Reactor::ACE_WFMO_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : signal_handler_ (0),
+ delete_signal_handler_ (0),
+ timer_queue_ (0),
+ delete_timer_queue_ (0),
+ delete_handler_rep_ (0),
+ delete_notify_handler_ (0),
+ lock_adapter_ (lock_),
+ handler_rep_ (*this),
+ // this event is initially signaled
+ ok_to_wait_ (1),
+ // this event is initially unsignaled
+ wakeup_all_threads_ (0),
+ // this event is initially unsignaled
+ waiting_to_change_state_ (0),
+ active_threads_ (0),
+ owner_ (ACE_Thread::self ()),
+ new_owner_ (0),
+ change_state_thread_ (0),
+ open_for_business_ (0),
+ deactivated_ (0)
+{
+ if (this->open (ACE_WFMO_Reactor::DEFAULT_SIZE, 0, sh, tq) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("WFMO_Reactor")));
+}
+
+ACE_WFMO_Reactor::ACE_WFMO_Reactor (size_t size,
+ int unused,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : signal_handler_ (0),
+ delete_signal_handler_ (0),
+ timer_queue_ (0),
+ delete_timer_queue_ (0),
+ delete_handler_rep_ (0),
+ delete_notify_handler_ (0),
+ lock_adapter_ (lock_),
+ handler_rep_ (*this),
+ // this event is initially signaled
+ ok_to_wait_ (1),
+ // this event is initially unsignaled
+ wakeup_all_threads_ (0),
+ // this event is initially unsignaled
+ waiting_to_change_state_ (0),
+ active_threads_ (0),
+ owner_ (ACE_Thread::self ()),
+ new_owner_ (0),
+ change_state_thread_ (0),
+ open_for_business_ (0),
+ deactivated_ (0)
+{
+ ACE_UNUSED_ARG (unused);
+
+ if (this->open (size, 0, sh, tq) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("WFMO_Reactor")));
+}
+
+int
+ACE_WFMO_Reactor::current_info (ACE_HANDLE, size_t &)
+{
+ return -1;
+}
+
+int
+ACE_WFMO_Reactor::open (size_t size,
+ int unused,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int disable_notify_pipe,
+ ACE_Reactor_Notify *notify)
+{
+ ACE_UNUSED_ARG (unused);
+ ACE_UNUSED_ARG (disable_notify_pipe);
+
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ // If we are already open, return -1
+ if (this->open_for_business_)
+ return -1;
+
+ // Timer Queue
+ if (this->delete_timer_queue_)
+ delete this->timer_queue_;
+
+ if (tq == 0)
+ {
+ ACE_NEW_RETURN (this->timer_queue_,
+ ACE_Timer_Heap,
+ -1);
+ this->delete_timer_queue_ = 1;
+ }
+ else
+ {
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = 0;
+ }
+
+ // Signal Handler
+ if (this->delete_signal_handler_)
+ delete this->signal_handler_;
+
+ if (sh == 0)
+ {
+ ACE_NEW_RETURN (this->signal_handler_,
+ ACE_Sig_Handler,
+ -1);
+ this->delete_signal_handler_ = 1;
+ }
+ else
+ {
+ this->signal_handler_ = sh;
+ this->delete_signal_handler_ = 0;
+ }
+
+ // Setup the atomic wait array (used later in <handle_events>)
+ this->atomic_wait_array_[0] = this->lock_.lock ().proc_mutex_;
+ this->atomic_wait_array_[1] = this->ok_to_wait_.handle ();
+
+ // This is to guard against reopens of WFMO_Reactor
+ if (this->delete_handler_rep_)
+ this->handler_rep_.~ACE_WFMO_Reactor_Handler_Repository ();
+
+ // Open the handle repository. Two additional handles for internal
+ // purposes
+ if (this->handler_rep_.open (size + 2) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("opening handler repository")),
+ -1);
+ else
+ this->delete_handler_rep_ = 1;
+
+ this->notify_handler_ = notify;
+
+ if (this->notify_handler_ == 0)
+ {
+ ACE_NEW_RETURN (this->notify_handler_,
+ ACE_WFMO_Reactor_Notify,
+ -1);
+
+ if (this->notify_handler_ == 0)
+ return -1;
+ else
+ this->delete_notify_handler_ = 1;
+ }
+
+ /* NOTE */
+ // The order of the following two registrations is very important
+
+ // Open the notification handler
+ if (this->notify_handler_->open (this, this->timer_queue_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("opening notify handler ")),
+ -1);
+
+ // Register for <wakeup_all_threads> event
+ if (this->register_handler (&this->wakeup_all_threads_handler_,
+ this->wakeup_all_threads_.handle ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("registering thread wakeup handler")),
+ -1);
+
+ // Since we have added two handles into the handler repository,
+ // update the <handler_repository_>
+ if (this->handler_rep_.changes_required ())
+ {
+ // Make necessary changes to the handler repository
+ this->handler_rep_.make_changes ();
+ // Turn off <wakeup_all_threads_> since all necessary changes
+ // have completed
+ this->wakeup_all_threads_.reset ();
+ }
+
+ // We are open for business
+ this->open_for_business_ = 1;
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::set_sig_handler (ACE_Sig_Handler *signal_handler)
+{
+ if (this->signal_handler_ != 0 && this->delete_signal_handler_ != 0)
+ delete this->signal_handler_;
+ this->signal_handler_ = signal_handler;
+ this->delete_signal_handler_ = 0;
+ return 0;
+}
+
+ACE_Timer_Queue *
+ACE_WFMO_Reactor::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+int
+ACE_WFMO_Reactor::timer_queue (ACE_Timer_Queue *tq)
+{
+ if (this->timer_queue_ != 0 && this->delete_timer_queue_ != 0)
+ delete this->timer_queue_;
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = 0;
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::set_timer_queue (ACE_Timer_Queue *tq)
+{
+ return this->timer_queue (tq);
+}
+
+int
+ACE_WFMO_Reactor::close (void)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ // If we are already closed, return error
+ if (!this->open_for_business_)
+ return -1;
+
+ // We are now closed
+ this->open_for_business_ = 0;
+ // This will unregister all handles
+ this->handler_rep_.close ();
+
+ return 0;
+}
+
+ACE_WFMO_Reactor::~ACE_WFMO_Reactor (void)
+{
+ // Assumption: No threads are left in the Reactor when this method
+ // is called (i.e., active_threads_ == 0)
+
+ // Close down
+ this->close ();
+
+ // Make necessary changes to the handler repository that we caused
+ // by <close>.
+ this->handler_rep_.make_changes ();
+
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = 0;
+ }
+
+ if (this->delete_signal_handler_)
+ {
+ delete this->signal_handler_;
+ this->signal_handler_ = 0;
+ this->delete_signal_handler_ = 0;
+ }
+
+ if (this->delete_notify_handler_)
+ {
+ delete this->notify_handler_;
+ this->notify_handler_ = 0;
+ this->delete_notify_handler_ = 0;
+ }
+}
+
+int
+ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask new_masks)
+{
+ // If this is a Winsock 1 system, the underlying event assignment will
+ // not work, so don't try. Winsock 1 must use ACE_Select_Reactor for
+ // reacting to socket activity.
+#if !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0)
+ ACE_UNUSED_ARG (event_handle);
+ ACE_UNUSED_ARG (io_handle);
+ ACE_UNUSED_ARG (event_handler);
+ ACE_UNUSED_ARG (new_masks);
+ ACE_NOTSUP_RETURN (-1);
+#else
+
+ // Make sure that the <handle> is valid
+ if (io_handle == ACE_INVALID_HANDLE)
+ io_handle = event_handler->get_handle ();
+
+ if (this->handler_rep_.invalid_handle (io_handle))
+ {
+ errno = ERROR_INVALID_HANDLE;
+ return -1;
+ }
+
+ long new_network_events = 0;
+ int delete_event = 0;
+ auto_ptr <ACE_Auto_Event> event;
+
+ // Look up the repository to see if the <event_handler> is already
+ // there.
+ ACE_Reactor_Mask old_masks;
+ int found = this->handler_rep_.modify_network_events_i (io_handle,
+ new_masks,
+ old_masks,
+ new_network_events,
+ event_handle,
+ delete_event,
+ ACE_Reactor::ADD_MASK);
+
+ // Check to see if the user passed us a valid event; If not then we
+ // need to create one
+ if (event_handle == ACE_INVALID_HANDLE)
+ {
+ // Note: don't change this since some C++ compilers have
+ // <auto_ptr>s that don't work properly...
+ auto_ptr<ACE_Auto_Event> tmp (new ACE_Auto_Event);
+ event = tmp;
+ event_handle = event->handle ();
+ delete_event = 1;
+ }
+
+ int result = ::WSAEventSelect ((SOCKET) io_handle,
+ event_handle,
+ new_network_events);
+ // If we had found the <Event_Handler> there is nothing more to do
+ if (found)
+ return result;
+ else if (result != SOCKET_ERROR &&
+ this->handler_rep_.bind_i (1,
+ event_handler,
+ new_network_events,
+ io_handle,
+ event_handle,
+ delete_event) != -1)
+ {
+ // The <event_handler> was not found in the repository, add to
+ // the repository.
+ if (delete_event)
+ {
+ // Clear out the handle in the ACE_Auto_Event so that when
+ // it is destroyed, the handle isn't closed out from under
+ // the reactor. After setting it, running down the event
+ // (via auto_ptr<> event, above) at function return will
+ // cause an error because it'll try to close an invalid handle.
+ // To avoid that smashing the errno value, save the errno
+ // here, explicitly remove the event so the dtor won't do it
+ // again, then restore errno.
+ ACE_Errno_Guard guard (errno);
+ event->handle (ACE_INVALID_HANDLE);
+ event->remove ();
+ }
+ return 0;
+ }
+ else
+ return -1;
+#endif /* ACE_HAS_PHARLAP */
+}
+
+int
+ACE_WFMO_Reactor::mask_ops_i (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask new_masks,
+ int operation)
+{
+ // Make sure that the <handle> is valid
+ if (this->handler_rep_.invalid_handle (io_handle))
+ return -1;
+
+ long new_network_events = 0;
+ int delete_event = 0;
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE;
+
+ // Look up the repository to see if the <Event_Handler> is already
+ // there.
+ ACE_Reactor_Mask old_masks;
+ int found = this->handler_rep_.modify_network_events_i (io_handle,
+ new_masks,
+ old_masks,
+ new_network_events,
+ event_handle,
+ delete_event,
+ operation);
+ if (found)
+ {
+ int result = ::WSAEventSelect ((SOCKET) io_handle,
+ event_handle,
+ new_network_events);
+ if (result == 0)
+ return old_masks;
+ else
+ return result;
+ }
+ else
+ return -1;
+}
+
+
+
+int
+ACE_WFMO_Reactor_Handler_Repository::modify_network_events_i (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask new_masks,
+ ACE_Reactor_Mask &old_masks,
+ long &new_network_events,
+ ACE_HANDLE &event_handle,
+ int &delete_event,
+ int operation)
+{
+ long *modified_network_events = &new_network_events;
+ int found = 0;
+ size_t i;
+
+ // First go through the current entries
+ //
+ // Look for all entries in the current handles for matching handle
+ // (except those that have been scheduled for deletion)
+ for (i = 0; i < this->max_handlep1_ && !found; i++)
+ if (io_handle == this->current_info_[i].io_handle_ &&
+ !this->current_info_[i].delete_entry_)
+ {
+ found = 1;
+ modified_network_events = &this->current_info_[i].network_events_;
+ delete_event = this->current_info_[i].delete_event_;
+ event_handle = this->current_handles_[i];
+ }
+
+ // Then pass through the suspended handles
+ //
+ // Look for all entries in the suspended handles for matching handle
+ // (except those that have been scheduled for deletion)
+ for (i = 0; i < this->suspended_handles_ && !found; i++)
+ if (io_handle == this->current_suspended_info_[i].io_handle_ &&
+ !this->current_suspended_info_[i].delete_entry_)
+ {
+ found = 1;
+ modified_network_events = &this->current_suspended_info_[i].network_events_;
+ delete_event = this->current_suspended_info_[i].delete_event_;
+ event_handle = this->current_suspended_info_[i].event_handle_;
+ }
+
+ // Then check the to_be_added handles
+ //
+ // Look for all entries in the to_be_added handles for matching
+ // handle (except those that have been scheduled for deletion)
+ for (i = 0; i < this->handles_to_be_added_ && !found; i++)
+ if (io_handle == this->to_be_added_info_[i].io_handle_ &&
+ !this->to_be_added_info_[i].delete_entry_)
+ {
+ found = 1;
+ modified_network_events = &this->to_be_added_info_[i].network_events_;
+ delete_event = this->to_be_added_info_[i].delete_event_;
+ event_handle = this->to_be_added_info_[i].event_handle_;
+ }
+
+ old_masks = this->bit_ops (*modified_network_events,
+ new_masks,
+ operation);
+
+ new_network_events = *modified_network_events;
+
+ return found;
+}
+
+int
+ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask user_masks,
+ ACE_Event_Handler **user_event_handler)
+{
+ int found = 0;
+ size_t i = 0;
+ ACE_Event_Handler *event_handler = 0;
+ long existing_masks = 0;
+
+ // Look for the handle first
+
+ // First go through the current entries
+ //
+ // Look for all entries in the current handles for matching handle
+ // (except those that have been scheduled for deletion)
+ for (i = 0; i < this->max_handlep1_ && !found; i++)
+ if ((handle == this->current_info_[i].io_handle_ ||
+ handle == this->current_handles_[i]) &&
+ !this->current_info_[i].delete_entry_)
+ {
+ found = 1;
+ event_handler = this->current_info_[i].event_handler_;
+ existing_masks = this->current_info_[i].network_events_;
+ }
+
+ // Then pass through the suspended handles
+ //
+ // Look for all entries in the suspended handles for matching handle
+ // (except those that have been scheduled for deletion)
+ for (i = 0; i < this->suspended_handles_ && !found; i++)
+ if ((handle == this->current_suspended_info_[i].io_handle_ ||
+ handle == this->current_suspended_info_[i].event_handle_) &&
+ !this->current_suspended_info_[i].delete_entry_)
+ {
+ found = 1;
+ event_handler = this->current_suspended_info_[i].event_handler_;
+ existing_masks = this->current_suspended_info_[i].network_events_;
+ }
+
+ // Then check the to_be_added handles
+ //
+ // Look for all entries in the to_be_added handles for matching
+ // handle (except those that have been scheduled for deletion)
+ for (i = 0; i < this->handles_to_be_added_ && !found; i++)
+ if ((handle == this->to_be_added_info_[i].io_handle_ ||
+ handle == this->to_be_added_info_[i].event_handle_) &&
+ !this->to_be_added_info_[i].delete_entry_)
+ {
+ found = 1;
+ event_handler = this->to_be_added_info_[i].event_handler_;
+ existing_masks = this->to_be_added_info_[i].network_events_;
+ }
+
+ // If the handle is not found, return failure.
+ if (!found)
+ return -1;
+
+ // Otherwise, make sure that the masks that the user is looking for
+ // are on.
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::READ_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_READ)
+ && !ACE_BIT_ENABLED (existing_masks, FD_CLOSE))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::WRITE_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_WRITE))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::EXCEPT_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_OOB))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::ACCEPT_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_ACCEPT))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::CONNECT_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_CONNECT))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::QOS_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_QOS))
+ found = 0;
+
+ if (found &&
+ ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::GROUP_QOS_MASK))
+ if (!ACE_BIT_ENABLED (existing_masks, FD_GROUP_QOS))
+ found = 0;
+
+ if (found &&
+ user_event_handler)
+ *user_event_handler = event_handler;
+
+ if (found)
+ return 0;
+ else
+ return -1;
+}
+
+// Waits for and dispatches all events. Returns -1 on error, 0 if
+// max_wait_time expired, or the number of events that were dispatched.
+int
+ACE_WFMO_Reactor::event_handling (ACE_Time_Value *max_wait_time,
+ int alertable)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::event_handling");
+
+ // Make sure we are not closed
+ if (!this->open_for_business_ || this->deactivated_)
+ return -1;
+
+ // Stash the current time -- the destructor of this object will
+ // automatically compute how much time elapsed since this method was
+ // called.
+ ACE_Countdown_Time countdown (max_wait_time);
+
+ // Check to see if it is ok to enter ::WaitForMultipleObjects
+ // This will acquire <this->lock_> on success
+ // On failure, the lock will not be acquired
+ int result = this->ok_to_wait (max_wait_time, alertable);
+ if (result != 1)
+ return result;
+
+ // Increment the number of active threads
+ this->active_threads_++;
+
+ // Release the <lock_>
+ this->lock_.release ();
+
+ // Update the countdown to reflect time waiting to play with the
+ // mut and event.
+ countdown.update ();
+
+ do
+ {
+ // Calculate timeout
+ int timeout = this->calculate_timeout (max_wait_time);
+
+ // Wait for event to happen
+ int wait_status = this->wait_for_multiple_events (timeout,
+ alertable);
+
+ // Upcall
+ result = this->safe_dispatch (wait_status);
+ if (0 == result)
+ {
+ // wait_for_multiple_events timed out without dispatching
+ // anything. Because of rounding and conversion errors and
+ // such, it could be that the wait loop timed out, but
+ // the timer queue said it wasn't quite ready to expire a
+ // timer. In this case, max_wait_time won't have quite been
+ // reduced to 0, and we need to go around again. If max_wait_time
+ // is all the way to 0, just return, as the entire time the
+ // caller wanted to wait has been used up.
+ countdown.update (); // Reflect time waiting for events
+ if (0 == max_wait_time || max_wait_time->usec () == 0)
+ break;
+ }
+ }
+ while (result == 0);
+
+ return result;
+}
+
+int
+ACE_WFMO_Reactor::ok_to_wait (ACE_Time_Value *max_wait_time,
+ int alertable)
+{
+ // Calculate the max time we should spend here
+ //
+ // Note: There is really no need to involve the <timer_queue_> here
+ // because even if a timeout in the <timer_queue_> does expire we
+ // will not be able to dispatch it
+ int timeout = max_wait_time == 0 ? INFINITE : max_wait_time->msec ();
+
+ // Atomically wait for both the <lock_> and <ok_to_wait_> event
+ DWORD result = 0;
+ while (1)
+ {
+#if defined (ACE_HAS_PHARLAP)
+ // PharLap doesn't implement WaitForMultipleObjectsEx, and doesn't
+ // do async I/O, so it's not needed in this case anyway.
+ result = ::WaitForMultipleObjects (sizeof this->atomic_wait_array_ / sizeof (ACE_HANDLE),
+ this->atomic_wait_array_,
+ TRUE,
+ timeout);
+#else
+ result = ::WaitForMultipleObjectsEx (sizeof this->atomic_wait_array_ / sizeof (ACE_HANDLE),
+ this->atomic_wait_array_,
+ TRUE,
+ timeout,
+ alertable);
+#endif /* ACE_HAS_PHARLAP */
+
+ if (result != WAIT_IO_COMPLETION)
+ break;
+ }
+
+ switch (result)
+ {
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return 0;
+ case WAIT_FAILED:
+ case WAIT_ABANDONED_0:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ default:
+ break;
+ }
+
+ // It is ok to enter ::WaitForMultipleObjects
+ return 1;
+}
+
+int
+ACE_WFMO_Reactor::wait_for_multiple_events (int timeout,
+ int alertable)
+{
+ // Wait for any of handles_ to be active, or until timeout expires.
+ // If <alertable> is enabled allow asynchronous completion of
+ // ReadFile and WriteFile operations.
+#if defined (ACE_HAS_PHARLAP)
+ // PharLap doesn't do async I/O and doesn't implement
+ // WaitForMultipleObjectsEx, so use WaitForMultipleObjects.
+ ACE_UNUSED_ARG (alertable);
+ return ::WaitForMultipleObjects (this->handler_rep_.max_handlep1 (),
+ this->handler_rep_.handles (),
+ FALSE,
+ timeout);
+#else
+ return ::WaitForMultipleObjectsEx (this->handler_rep_.max_handlep1 (),
+ this->handler_rep_.handles (),
+ FALSE,
+ timeout,
+ alertable);
+#endif /* ACE_HAS_PHARLAP */
+}
+
+DWORD
+ACE_WFMO_Reactor::poll_remaining_handles (size_t slot)
+{
+ return ::WaitForMultipleObjects (this->handler_rep_.max_handlep1 () - slot,
+ this->handler_rep_.handles () + slot,
+ FALSE,
+ 0);
+}
+
+int
+ACE_WFMO_Reactor::calculate_timeout (ACE_Time_Value *max_wait_time)
+{
+ ACE_Time_Value *time = 0;
+ if (this->owner_ == ACE_Thread::self ())
+ time = this->timer_queue_->calculate_timeout (max_wait_time);
+ else
+ time = max_wait_time;
+
+ if (time == 0)
+ return INFINITE;
+ else
+ return time->msec ();
+}
+
+
+int
+ACE_WFMO_Reactor::expire_timers (void)
+{
+ // If "owner" thread
+ if (ACE_Thread::self () == this->owner_)
+ // expire all pending timers.
+ return this->timer_queue_->expire ();
+
+ else
+ // Nothing to expire
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::dispatch (int wait_status)
+{
+ int handlers_dispatched = 0;
+
+ // Expire timers
+ handlers_dispatched += this->expire_timers ();
+
+ switch ((DWORD)wait_status)
+ {
+ case WAIT_FAILED: // Failure.
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+
+ case WAIT_TIMEOUT: // Timeout.
+ errno = ETIME;
+ return handlers_dispatched;
+
+ case WAIT_IO_COMPLETION: // APC.
+ return handlers_dispatched;
+
+ default: // Dispatch.
+ // We'll let dispatch worry about abandoned mutes.
+ handlers_dispatched += this->dispatch_handles (wait_status);
+ return handlers_dispatched;
+ }
+}
+
+// Dispatches any active handles from <handles_[slot]> to
+// <handles_[max_handlep1_]>, polling through our handle set looking
+// for active handles.
+int
+ACE_WFMO_Reactor::dispatch_handles (size_t wait_status)
+{
+ // dispatch_slot is the absolute slot. Only += is used to
+ // increment it.
+ size_t dispatch_slot = 0;
+
+ // Cache this value, this is the absolute value.
+ size_t max_handlep1 = this->handler_rep_.max_handlep1 ();
+
+ // nCount starts off at <max_handlep1>, this is a transient count of
+ // handles last waited on.
+ size_t nCount = max_handlep1;
+
+ for (int number_of_handlers_dispatched = 1;
+ ;
+ number_of_handlers_dispatched++)
+ {
+ bool ok = (
+#if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530)) \
+ && !defined (ghs) \
+ && !defined (__MINGW32__)
+ // wait_status is unsigned in Borland, Green Hills
+ // and mingw32;
+ // This >= is always true, with a warning.
+ wait_status >= WAIT_OBJECT_0 &&
+#endif
+ wait_status <= (WAIT_OBJECT_0 + nCount));
+ if (ok)
+ dispatch_slot += wait_status - WAIT_OBJECT_0;
+ else
+ // Otherwise, a handle was abandoned.
+ dispatch_slot += wait_status - WAIT_ABANDONED_0;
+
+ // Dispatch handler
+ if (this->dispatch_handler (dispatch_slot, max_handlep1) == -1)
+ return -1;
+
+ // Increment slot
+ dispatch_slot++;
+
+ // We're done.
+ if (dispatch_slot >= max_handlep1)
+ return number_of_handlers_dispatched;
+
+ // Readjust nCount
+ nCount = max_handlep1 - dispatch_slot;
+
+ // Check the remaining handles
+ wait_status = this->poll_remaining_handles (dispatch_slot);
+ switch (wait_status)
+ {
+ case WAIT_FAILED: // Failure.
+ ACE_OS::set_errno_to_last_error ();
+ /* FALLTHRU */
+ case WAIT_TIMEOUT:
+ // There are no more handles ready, we can return.
+ return number_of_handlers_dispatched;
+ }
+ }
+}
+
+int
+ACE_WFMO_Reactor::dispatch_handler (size_t slot,
+ size_t max_handlep1)
+{
+ // Check if there are window messages that need to be dispatched
+ if (slot == max_handlep1)
+ return this->dispatch_window_messages ();
+
+ // Dispatch the handler if it has not been scheduled for deletion.
+ // Note that this is a very week test if there are multiple threads
+ // dispatching this slot as no locks are held here. Generally, you
+ // do not want to do something like deleting the this pointer in
+ // handle_close() if you have registered multiple times and there is
+ // more than one thread in WFMO_Reactor->handle_events().
+ else if (!this->handler_rep_.scheduled_for_deletion (slot))
+ {
+ ACE_HANDLE event_handle = *(this->handler_rep_.handles () + slot);
+
+ if (this->handler_rep_.current_info ()[slot].io_entry_)
+ return this->complex_dispatch_handler (slot,
+ event_handle);
+ else
+ return this->simple_dispatch_handler (slot,
+ event_handle);
+ }
+ else
+ // The handle was scheduled for deletion, so we will skip it.
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::simple_dispatch_handler (int slot,
+ ACE_HANDLE event_handle)
+{
+ // This dispatch is used for non-I/O entires
+
+ // Assign the ``signaled'' HANDLE so that callers can get it.
+#if defined (ACE_HAS_PACE)
+ // siginfo_t is typedef'd to a pace_siginfo_t where there
+ // exists no constructor.
+ siginfo_t sig;
+ sig.si_handle_ = event_handle;
+#else
+ // siginfo_t is an ACE - specific fabrication. Constructor exists.
+ siginfo_t sig (event_handle);
+#endif // ACE_HAS_PACE
+
+ ACE_Event_Handler *eh =
+ this->handler_rep_.current_info ()[slot].event_handler_;
+
+ // Upcall
+ if (eh->handle_signal (0, &sig) == -1)
+ this->handler_rep_.unbind (event_handle,
+ ACE_Event_Handler::NULL_MASK);
+
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor::complex_dispatch_handler (int slot,
+ ACE_HANDLE event_handle)
+{
+ // This dispatch is used for I/O entires.
+
+ ACE_WFMO_Reactor_Handler_Repository::Current_Info &current_info =
+ this->handler_rep_.current_info ()[slot];
+
+ WSANETWORKEVENTS events;
+ ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;
+ if (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,
+ event_handle,
+ &events) == SOCKET_ERROR)
+ problems = ACE_Event_Handler::ALL_EVENTS_MASK;
+ else
+ {
+ // Prepare for upcalls. Clear the bits from <events> representing
+ // events the handler is not interested in. If there are any left,
+ // do the upcall(s). upcall will replace events.lNetworkEvents
+ // with bits representing any functions that requested a repeat
+ // callback before checking handles again. In this case, continue
+ // to call back unless the handler is unregistered as a result of
+ // one of the upcalls. The way this is written, the upcalls will
+ // keep being done even if one or more upcalls reported problems.
+ // In practice this may turn out not so good, but let's see. If any
+ // problems, please notify Steve Huston <shuston@riverace.com>
+ // before or after you change this code.
+ events.lNetworkEvents &= current_info.network_events_;
+ while (events.lNetworkEvents != 0)
+ {
+ // Upcall
+ problems |= this->upcall (current_info.event_handler_,
+ current_info.io_handle_,
+ events);
+ if (this->handler_rep_.scheduled_for_deletion (slot))
+ break;
+ }
+ }
+
+ if (problems != ACE_Event_Handler::NULL_MASK
+ && !this->handler_rep_.scheduled_for_deletion (slot) )
+ this->handler_rep_.unbind (event_handle, problems);
+
+ return 0;
+}
+
+ACE_Reactor_Mask
+ACE_WFMO_Reactor::upcall (ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ WSANETWORKEVENTS &events)
+{
+ // This method figures out what exactly has happened to the socket
+ // and then calls appropriate methods.
+ ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;
+
+ // Go through the events and do the indicated upcalls. If the handler
+ // doesn't want to be called back, clear the bit for that event.
+ // At the end, set the bits back to <events> to request a repeat call.
+
+ long actual_events = events.lNetworkEvents;
+ int action;
+
+ if (ACE_BIT_ENABLED (actual_events, FD_READ))
+ {
+ action = event_handler->handle_input (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_READ);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_CLOSE)
+ && ACE_BIT_DISABLED (problems, ACE_Event_Handler::READ_MASK))
+ {
+ action = event_handler->handle_input (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_CLOSE);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_ACCEPT))
+ {
+ action = event_handler->handle_input (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_ACCEPT);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::ACCEPT_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_WRITE))
+ {
+ action = event_handler->handle_output (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_WRITE);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::WRITE_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_CONNECT))
+ {
+ if (events.iErrorCode[FD_CONNECT_BIT] == 0)
+ {
+ // Successful connect
+ action = event_handler->handle_output (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_CONNECT);
+ if (action == -1)
+ ACE_SET_BITS (problems,
+ ACE_Event_Handler::CONNECT_MASK);
+ }
+ }
+ // Unsuccessful connect
+ else
+ {
+ action = event_handler->handle_input (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_CONNECT);
+ if (action == -1)
+ ACE_SET_BITS (problems,
+ ACE_Event_Handler::CONNECT_MASK);
+ }
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_OOB))
+ {
+ action = event_handler->handle_exception (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_OOB);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::EXCEPT_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_QOS))
+ {
+ action = event_handler->handle_qos (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_QOS);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::QOS_MASK);
+ }
+ }
+
+ if (ACE_BIT_ENABLED (actual_events, FD_GROUP_QOS))
+ {
+ action = event_handler->handle_group_qos (io_handle);
+ if (action <= 0)
+ {
+ ACE_CLR_BITS (actual_events, FD_GROUP_QOS);
+ if (action == -1)
+ ACE_SET_BITS (problems, ACE_Event_Handler::GROUP_QOS_MASK);
+ }
+ }
+
+ events.lNetworkEvents = actual_events;
+ return problems;
+}
+
+
+int
+ACE_WFMO_Reactor::update_state (void)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, monitor, this->lock_, -1);
+
+ // Decrement active threads
+ this->active_threads_--;
+
+ // Check if the state of the handler repository has changed or new
+ // owner has to be set
+ if (this->handler_rep_.changes_required () || this->new_owner ())
+ {
+ if (this->change_state_thread_ == 0)
+ // Try to become the thread which will be responsible for the
+ // changes
+ {
+ this->change_state_thread_ = ACE_Thread::self ();
+ // Make sure no new threads are allowed to enter
+ this->ok_to_wait_.reset ();
+
+ if (this->active_threads_ > 0)
+ // Check for other active threads
+ {
+ // Wake up all other threads
+ this->wakeup_all_threads_.signal ();
+ // Release <lock_>
+ monitor.release ();
+ // Go to sleep waiting for all other threads to get done
+ this->waiting_to_change_state_.wait ();
+ // Re-acquire <lock_> again
+ monitor.acquire ();
+ }
+
+ // Note that make_changes() calls into user code which can
+ // request other changes. So keep looping until all
+ // requested changes are completed.
+ while (this->handler_rep_.changes_required ())
+ // Make necessary changes to the handler repository
+ this->handler_rep_.make_changes ();
+ if (this->new_owner ())
+ // Update the owner
+ this->change_owner ();
+ // Turn off <wakeup_all_threads_>
+ this->wakeup_all_threads_.reset ();
+ // Let everyone know that it is ok to go ahead
+ this->ok_to_wait_.signal ();
+ // Reset this flag
+ this->change_state_thread_ = 0;
+ }
+ else if (this->active_threads_ == 0)
+ // This thread did not get a chance to become the change
+ // thread. If it is the last one out, it will wakeup the
+ // change thread
+ this->waiting_to_change_state_.signal ();
+ }
+ // This is if we were woken up explicitily by the user and there are
+ // no state changes required.
+ else if (this->active_threads_ == 0)
+ // Turn off <wakeup_all_threads_>
+ this->wakeup_all_threads_.reset ();
+
+ return 0;
+}
+
+void
+ACE_WFMO_Reactor::dump (void) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Count of currently active threads = %d\n"),
+ this->active_threads_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ID of owner thread = %d\n"),
+ this->owner_));
+
+ this->handler_rep_.dump ();
+ this->signal_handler_->dump ();
+ this->timer_queue_->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_WFMO_Reactor_Notify::dispatch_notifications (int & /*number_of_active_handles*/,
+ ACE_Handle_Set & /*rd_mask*/)
+{
+ return -1;
+}
+
+int
+ACE_WFMO_Reactor_Notify::is_dispatchable (ACE_Notification_Buffer & /*buffer*/)
+{
+ return 0;
+}
+
+ACE_HANDLE
+ACE_WFMO_Reactor_Notify::notify_handle (void)
+{
+ return ACE_INVALID_HANDLE;
+}
+
+int
+ACE_WFMO_Reactor_Notify::read_notify_pipe (ACE_HANDLE ,
+ ACE_Notification_Buffer &)
+{
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &)
+{
+ return 0;
+}
+
+int
+ACE_WFMO_Reactor_Notify::close (void)
+{
+ return -1;
+}
+
+ACE_WFMO_Reactor_Notify::ACE_WFMO_Reactor_Notify (void)
+ : timer_queue_ (0),
+ max_notify_iterations_ (-1)
+{
+}
+
+int
+ACE_WFMO_Reactor_Notify::open (ACE_Reactor_Impl *wfmo_reactor,
+ ACE_Timer_Queue *timer_queue,
+ int ignore_notify)
+{
+ ACE_UNUSED_ARG (ignore_notify);
+ timer_queue_ = timer_queue;
+ return wfmo_reactor->register_handler (this);
+}
+
+ACE_HANDLE
+ACE_WFMO_Reactor_Notify::get_handle (void) const
+{
+ return this->wakeup_one_thread_.handle ();
+}
+
+// Handle all pending notifications.
+
+int
+ACE_WFMO_Reactor_Notify::handle_signal (int signum,
+ siginfo_t *siginfo,
+ ucontext_t *)
+{
+ ACE_UNUSED_ARG (signum);
+
+ // Just check for sanity...
+ if (siginfo->si_handle_ != this->wakeup_one_thread_.handle ())
+ return -1;
+
+ // This will get called when <WFMO_Reactor->wakeup_one_thread_> event
+ // is signaled.
+ // ACE_DEBUG ((LM_DEBUG,
+ // ACE_LIB_TEXT ("(%t) waking up to handle internal notifications\n")));
+
+ for (int i = 1; ; i++)
+ {
+ ACE_Message_Block *mb = 0;
+ // Copy ACE_Time_Value::zero since dequeue_head will modify it.
+ ACE_Time_Value zero_timeout (ACE_Time_Value::zero);
+ if (this->message_queue_.dequeue_head (mb, &zero_timeout) == -1)
+ {
+ if (errno == EWOULDBLOCK)
+ // We've reached the end of the processing, return
+ // normally.
+ return 0;
+ else
+ return -1; // Something weird happened...
+ }
+ else
+ {
+ ACE_Notification_Buffer *buffer =
+ (ACE_Notification_Buffer *) mb->base ();
+
+ // If eh == 0 then we've got major problems! Otherwise, we
+ // need to dispatch the appropriate handle_* method on the
+ // ACE_Event_Handler pointer we've been passed.
+
+ if (buffer->eh_ != 0)
+ {
+ int result = 0;
+
+ switch (buffer->mask_)
+ {
+ case ACE_Event_Handler::READ_MASK:
+ case ACE_Event_Handler::ACCEPT_MASK:
+ result = buffer->eh_->handle_input (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::WRITE_MASK:
+ result = buffer->eh_->handle_output (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::EXCEPT_MASK:
+ result = buffer->eh_->handle_exception (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::QOS_MASK:
+ result = buffer->eh_->handle_qos (ACE_INVALID_HANDLE);
+ break;
+ case ACE_Event_Handler::GROUP_QOS_MASK:
+ result = buffer->eh_->handle_group_qos (ACE_INVALID_HANDLE);
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("invalid mask = %d\n"),
+ buffer->mask_));
+ break;
+ }
+ if (result == -1)
+ buffer->eh_->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::EXCEPT_MASK);
+ }
+
+ // Make sure to delete the memory regardless of success or
+ // failure!
+ mb->release ();
+
+ // Bail out if we've reached the <max_notify_iterations_>.
+ // Note that by default <max_notify_iterations_> is -1, so
+ // we'll loop until we're done.
+ if (i == this->max_notify_iterations_)
+ {
+ // If there are still notification in the queue, we need
+ // to wake up again
+ if (!this->message_queue_.is_empty ())
+ this->wakeup_one_thread_.signal ();
+
+ // Break the loop as we have reached max_notify_iterations_
+ return 0;
+ }
+ }
+ }
+}
+
+// Notify the WFMO_Reactor, potentially enqueueing the
+// <ACE_Event_Handler> for subsequent processing in the WFMO_Reactor
+// thread of control.
+
+int
+ACE_WFMO_Reactor_Notify::notify (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ if (eh != 0)
+ {
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (sizeof (ACE_Notification_Buffer)),
+ -1);
+
+ ACE_Notification_Buffer *buffer =
+ (ACE_Notification_Buffer *) mb->base ();
+ buffer->eh_ = eh;
+ buffer->mask_ = mask;
+
+ // Convert from relative time to absolute time by adding the
+ // current time of day. This is what <ACE_Message_Queue>
+ // expects.
+ if (timeout != 0)
+ *timeout += timer_queue_->gettimeofday ();
+
+ if (this->message_queue_.enqueue_tail
+ (mb, timeout) == -1)
+ {
+ mb->release ();
+ return -1;
+ }
+ }
+
+ return this->wakeup_one_thread_.signal ();
+}
+
+void
+ACE_WFMO_Reactor_Notify::max_notify_iterations (int iterations)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Notify::max_notify_iterations");
+ // Must always be > 0 or < 0 to optimize the loop exit condition.
+ if (iterations == 0)
+ iterations = 1;
+
+ this->max_notify_iterations_ = iterations;
+}
+
+int
+ACE_WFMO_Reactor_Notify::max_notify_iterations (void)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Notify::max_notify_iterations");
+ return this->max_notify_iterations_;
+}
+
+int
+ACE_WFMO_Reactor_Notify::purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Notify::purge_pending_notifications");
+
+ // Go over message queue and take out all the matching event
+ // handlers. If eh == 0, purge all. Note that reactor notifies (no
+ // handler specified) are never purged, as this may lose a needed
+ // notify the reactor queued for itself.
+
+ if (this->message_queue_.is_empty ())
+ return 0;
+
+ // Guard against new and/or delivered notifications while purging.
+ // WARNING!!! The use of the notification queue's lock object for
+ // this guard makes use of the knowledge that on Win32, the mutex
+ // protecting the queue is really a CriticalSection, which is
+ // recursive. This is how we can get away with locking it down here
+ // and still calling member functions on the queue object.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, monitor, this->message_queue_.lock(), -1);
+
+ // first, copy all to our own local queue. Since we've locked everyone out
+ // of here, there's no need to use any synchronization on this queue.
+ ACE_Message_Queue<ACE_NULL_SYNCH> local_queue;
+
+ size_t queue_size = this->message_queue_.message_count ();
+ int number_purged = 0;
+
+ size_t index;
+
+ for (index = 0; index < queue_size; ++index)
+ {
+ ACE_Message_Block *mb;
+ if (-1 == this->message_queue_.dequeue_head (mb))
+ return -1; // This shouldn't happen...
+
+ ACE_Notification_Buffer *buffer =
+ ACE_reinterpret_cast (ACE_Notification_Buffer *, mb->base ());
+
+ // If this is not a Reactor notify (it is for a particular handler),
+ // and it matches the specified handler (or purging all),
+ // and applying the mask would totally eliminate the notification, then
+ // release it and count the number purged.
+ if ((0 != buffer->eh_) &&
+ (0 == eh || eh == buffer->eh_) &&
+ ACE_BIT_DISABLED (buffer->mask_, ~mask)) // the existing notification mask
+ // is left with nothing when
+ // applying the mask
+ {
+ mb->release ();
+ ++number_purged;
+ }
+ else
+ {
+ // To preserve it, move it to the local_queue. But first, if
+ // this is not a Reactor notify (it is for a
+ // particularhandler), and it matches the specified handler
+ // (or purging all), then apply the mask
+ if ((0 != buffer->eh_) &&
+ (0 == eh || eh == buffer->eh_))
+ ACE_CLR_BITS(buffer->mask_, mask);
+ if (-1 == local_queue.enqueue_head (mb))
+ return -1;
+ }
+ }
+
+ if (this->message_queue_.message_count ())
+ { // Should be empty!
+ ACE_ASSERT (0);
+ return -1;
+ }
+
+ // Now copy back from the local queue to the class queue, taking
+ // care to preserve the original order...
+ queue_size = local_queue.message_count ();
+ for (index = 0; index < queue_size; ++index)
+ {
+ ACE_Message_Block *mb;
+ if (-1 == local_queue.dequeue_head (mb))
+ {
+ ACE_ASSERT (0);
+ return -1;
+ }
+
+ if (-1 == this->message_queue_.enqueue_head (mb))
+ {
+ ACE_ASSERT (0);
+ return -1;
+ }
+ }
+
+ return number_purged;
+}
+
+void
+ACE_WFMO_Reactor_Notify::dump (void) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Notify::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->timer_queue_->dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Max. iteration: %d\n"),
+ this->max_notify_iterations_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_WFMO_Reactor::max_notify_iterations (int iterations)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::max_notify_iterations");
+ ACE_GUARD (ACE_Process_Mutex, monitor, this->lock_);
+
+ // Must always be > 0 or < 0 to optimize the loop exit condition.
+ this->notify_handler_->max_notify_iterations (iterations);
+}
+
+int
+ACE_WFMO_Reactor::max_notify_iterations (void)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::max_notify_iterations");
+ ACE_GUARD_RETURN (ACE_Process_Mutex, monitor, this->lock_, -1);
+
+ return this->notify_handler_->max_notify_iterations ();
+}
+
+int
+ACE_WFMO_Reactor::purge_pending_notifications (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::purge_pending_notifications");
+ if (this->notify_handler_ == 0)
+ return 0;
+ else
+ return this->notify_handler_->purge_pending_notifications (eh, mask);
+}
+
+int
+ACE_WFMO_Reactor::resumable_handler (void)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::resumable_handler");
+ return 0;
+}
+
+
+// No-op WinSOCK2 methods to help WFMO_Reactor compile
+#if !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0)
+int
+WSAEventSelect (SOCKET s,
+ WSAEVENT hEventObject,
+ long lNetworkEvents)
+{
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (hEventObject);
+ ACE_UNUSED_ARG (lNetworkEvents);
+
+ return -1;
+}
+
+int
+WSAEnumNetworkEvents (SOCKET s,
+ WSAEVENT hEventObject,
+ LPWSANETWORKEVENTS lpNetworkEvents)
+{
+ ACE_UNUSED_ARG (s);
+ ACE_UNUSED_ARG (hEventObject);
+ ACE_UNUSED_ARG (lpNetworkEvents);
+
+ return -1;
+}
+#endif /* !defined ACE_HAS_WINSOCK2 */
+
+#endif /* ACE_WIN32 */
diff --git a/ace/Demux/WFMO_Reactor.h b/ace/Demux/WFMO_Reactor.h
new file mode 100644
index 00000000000..02ed32ed6df
--- /dev/null
+++ b/ace/Demux/WFMO_Reactor.h
@@ -0,0 +1,1324 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file WFMO_Reactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author and Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_WFMO_REACTOR_H
+#define ACE_WFMO_REACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Signal.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Queue.h"
+#include "ace/Event_Handler.h"
+#include "ace/Synch.h"
+#include "ace/Reactor_Impl.h"
+#include "ace/Message_Queue.h"
+#include "ace/Process_Mutex.h"
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+// If we don't have WinSOCK2, we need these defined
+#if !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0)
+/*
+ * WinSock 2 extension -- bit values and indices for FD_XXX network events
+ */
+#define FD_READ_BIT 0
+#define FD_WRITE_BIT 1
+#define FD_OOB_BIT 2
+#define FD_ACCEPT_BIT 3
+#define FD_CONNECT_BIT 4
+#define FD_CLOSE_BIT 5
+#define FD_QOS_BIT 6
+#define FD_GROUP_QOS_BIT 7
+
+#define FD_QOS (1 << FD_QOS_BIT)
+#define FD_GROUP_QOS (1 << FD_GROUP_QOS_BIT)
+
+#define FD_MAX_EVENTS 8
+#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1)
+
+#define WSAEVENT HANDLE
+
+typedef struct _WSANETWORKEVENTS
+{
+ long lNetworkEvents;
+ int iErrorCode[FD_MAX_EVENTS];
+} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
+
+int WSAEventSelect (SOCKET s,
+ WSAEVENT hEventObject,
+ long lNetworkEvents);
+
+int WSAEnumNetworkEvents (SOCKET s,
+ WSAEVENT hEventObject,
+ LPWSANETWORKEVENTS lpNetworkEvents);
+
+#endif /* !defined ACE_HAS_WINSOCK2 */
+#endif /* defined (ACE_WIN32) && !define (ACE_HAS_WINCE) */
+
+// Forward decl.
+class ACE_WFMO_Reactor;
+class ACE_Handle_Set;
+
+/**
+ * @class ACE_Wakeup_All_Threads_Handler
+ *
+ * @brief This is a helper class whose sole purpose is to handle events
+ * on <ACE_WFMO_Reactor->wakeup_all_threads_>
+ */
+class ACE_Export ACE_Wakeup_All_Threads_Handler : public ACE_Event_Handler
+{
+public:
+ /// Called when the <ACE_WFMO_Reactor->wakeup_all_threads_>
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+};
+
+/**
+ * @class ACE_WFMO_Reactor_Handler_Repository
+ *
+ * @brief Used to map <ACE_HANDLE>s onto the appropriate
+ * <ACE_Event_Handler> * and other information.
+ */
+class ACE_Export ACE_WFMO_Reactor_Handler_Repository
+{
+public:
+ friend class ACE_WFMO_Reactor;
+ friend class ACE_WFMO_Reactor_Test;
+
+ /**
+ * @class Common_Info
+ *
+ * @brief This struct contains the necessary information for every
+ * <Event_Handler> entry. The reason the event is not in this
+ * structure is because we need to pass an event array into
+ * WaitForMultipleObjects and therefore keeping the events
+ * seperate makes sense.
+ */
+ class Common_Info
+ {
+ public:
+ /// This indicates whether this entry is for I/O or for a regular
+ /// event
+ int io_entry_;
+
+ /// The assosiated <Event_Handler>
+ ACE_Event_Handler *event_handler_;
+
+ /// The I/O handle related to the <Event_Handler>. This entry is
+ /// only valid if the <io_entry_> flag is true.
+ ACE_HANDLE io_handle_;
+
+ /**
+ * This is the set of events that the <Event_Handler> is
+ * interested in This entry is only valid if the <io_entry_> flag
+ * is true.
+ */
+ long network_events_;
+
+ /**
+ * This flag indicates that <WFMO_Reactor> created the event on
+ * behalf of the user. Therefore we need to clean this up when the
+ * <Event_Handler> removes itself from <WFMO_Reactor>. This entry
+ * is only valid if the <io_entry_> flag is true.
+ */
+ int delete_event_;
+
+ /// This is set when the entry needed to be deleted.
+ int delete_entry_;
+
+ /**
+ * These are the masks related to <handle_close> for the
+ * <Event_Handler>. This is only valid when <delete_entry_> is
+ * set.
+ */
+ ACE_Reactor_Mask close_masks_;
+
+ /// Constructor used for initializing the structure
+ Common_Info (void);
+
+ /// Reset the state of the structure
+ void reset (void);
+
+ /// Set the structure to these new values
+ void set (int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry,
+ ACE_Reactor_Mask close_masks);
+
+ /// Set the structure to these new values
+ void set (Common_Info &common_info);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+ };
+
+ /**
+ * @class Current_Info
+ *
+ * @brief This structure inherits from the common structure to add
+ * information for current entries.
+ */
+ class Current_Info : public Common_Info
+ {
+ public:
+ /// This is set when the entry needed to be suspended.
+ int suspend_entry_;
+
+ /// Default constructor
+ Current_Info (void);
+
+ /// Reset the state of the structure
+ void reset (void);
+
+ /// Set the structure to these new values
+ void set (int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry = 0,
+ ACE_Reactor_Mask close_masks = ACE_Event_Handler::NULL_MASK,
+ int suspend_entry = 0);
+
+ /// Set the structure to these new values
+ void set (Common_Info &common_info,
+ int suspend_entry = 0);
+
+ /// Dump the state of an object.
+ void dump (ACE_HANDLE event_handle) const;
+ };
+
+ /**
+ * @class To_Be_Added_Info
+ *
+ * @brief This structure inherits from the common structure to add
+ * information for <to_be_added> entries.
+ */
+ class To_Be_Added_Info : public Common_Info
+ {
+ public:
+ /// Handle for the event
+ ACE_HANDLE event_handle_;
+
+ /// This is set when the entry needed to be suspended.
+ int suspend_entry_;
+
+ /// Default constructor
+ To_Be_Added_Info (void);
+
+ /// Reset the state of the structure
+ void reset (void);
+
+ /// Set the structure to these new values
+ void set (ACE_HANDLE event_handle,
+ int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry = 0,
+ ACE_Reactor_Mask close_masks = ACE_Event_Handler::NULL_MASK,
+ int suspend_entry = 0);
+
+ /// Set the structure to these new values
+ void set (ACE_HANDLE event_handle,
+ Common_Info &common_info,
+ int suspend_entry = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+ };
+
+ /**
+ * @class Suspended_Info
+ *
+ * @brief This structure inherits from the common structure to add
+ * information for suspended entries.
+ */
+ class Suspended_Info : public Common_Info
+ {
+ public:
+ /// Handle for the event
+ ACE_HANDLE event_handle_;
+
+ /// This is set when the entry needed to be resumed.
+ int resume_entry_;
+
+ /// Constructor used for initializing the structure
+ Suspended_Info (void);
+
+ /// Reset the state of the structure
+ void reset (void);
+
+ /// Set the structure to these new values
+ void set (ACE_HANDLE event_handle,
+ int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry = 0,
+ ACE_Reactor_Mask close_masks = 0,
+ int resume_entry = 0);
+
+ /// Set the structure to these new values
+ void set (ACE_HANDLE event_handle,
+ Common_Info &common_info,
+ int resume_entry = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+ };
+
+ /// Constructor.
+ ACE_WFMO_Reactor_Handler_Repository (ACE_WFMO_Reactor &wfmo_reactor);
+
+ /// Destructor.
+ virtual ~ACE_WFMO_Reactor_Handler_Repository (void);
+
+ /// Initialize the repository of the approriate <size>.
+ int open (size_t size);
+
+ /// Close down the handler repository.
+ int close (void);
+
+ // = Search structure operations.
+
+ /// Bind the <ACE_Event_Handler *> to the <ACE_HANDLE>. This is for
+ /// the simple event entry.
+ int bind (ACE_HANDLE, ACE_Event_Handler *);
+
+ /// Insert I/O <Event_Handler> entry into the system. This method
+ /// assumes that the lock are head *before* this method is invoked.
+ int bind_i (int io_entry,
+ ACE_Event_Handler *event_handler,
+ long network_events,
+ ACE_HANDLE io_handle,
+ ACE_HANDLE event_handle,
+ int delete_event);
+
+ /// Remove the binding of <ACE_HANDLE> in accordance with the <mask>.
+ int unbind (ACE_HANDLE,
+ ACE_Reactor_Mask mask);
+
+ /// Non-lock-grabbing version of <unbind>
+ int unbind_i (ACE_HANDLE,
+ ACE_Reactor_Mask mask,
+ int &changes_required);
+
+ /// Remove all bindings of <ACE_HANDLE, ACE_Event_Handler> tuples.
+ void unbind_all (void);
+
+ // = Sanity checking.
+
+ // Check the <handle> to make sure it's a valid ACE_HANDLE
+ int invalid_handle (ACE_HANDLE handle) const;
+
+ // = Accessors.
+ /// Maximum ACE_HANDLE value, plus 1.
+ size_t max_handlep1 (void) const;
+
+ /// Pointer to the beginning of the current array of <ACE_HANDLE>
+ /// *'s.
+ ACE_HANDLE *handles (void) const;
+
+ /// Pointer to the beginning of the current array of
+ /// <ACE_Event_Handler> *'s.
+ Current_Info *current_info (void) const;
+
+ /// Check if changes to the handle set are required.
+ virtual int changes_required (void);
+
+ /// Make changes to the handle set
+ virtual int make_changes (void);
+
+ /// Check to see if <slot> has been scheduled for deletion
+ int scheduled_for_deletion (size_t slot) const;
+
+ /**
+ * This method is used to calculate the network mask after a mask_op
+ * request to <WFMO_Reactor>. Note that because the <Event_Handler>
+ * may already be in the handler repository, we may have to find the
+ * old event and the old network events
+ */
+ int modify_network_events_i (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask new_masks,
+ ACE_Reactor_Mask &old_masks,
+ long &new_network_events,
+ ACE_HANDLE &event_handle,
+ int &delete_event,
+ int operation);
+
+ /// This method is used to change the network mask left (if any)
+ /// after a remove request to <WFMO_Reactor>
+ ACE_Reactor_Mask bit_ops (long &existing_masks,
+ ACE_Reactor_Mask to_be_removed_masks,
+ int operation);
+
+ /// Temporarily suspend entry
+ int suspend_handler_i (ACE_HANDLE handle,
+ int &changes_required);
+
+ /// Resume suspended entry
+ int resume_handler_i (ACE_HANDLE handle,
+ int &changes_required);
+
+ /// Deletions and suspensions in current_info_
+ int make_changes_in_current_infos (void);
+
+ /// Deletions and resumptions in current_suspended_info_
+ int make_changes_in_suspension_infos (void);
+
+ /// Deletions in to_be_added_info_, or transfers to current_info_ or
+ /// current_suspended_info_ from to_be_added_info_
+ int make_changes_in_to_be_added_infos (void);
+
+ /// Removes the <ACE_Event_Handler> at <slot> from the table.
+ int remove_handler_i (size_t slot,
+ ACE_Reactor_Mask mask);
+
+ /// Removes the <ACE_Event_Handler> at <slot> from the table.
+ int remove_suspended_handler_i (size_t slot,
+ ACE_Reactor_Mask mask);
+
+ /// Removes the <ACE_Event_Handler> at <slot> from the table.
+ int remove_to_be_added_handler_i (size_t slot,
+ ACE_Reactor_Mask to_be_removed_masks);
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to <mask>. Return the <event_handler> associated with this
+ * <handler> if <event_handler> != 0.
+ */
+ int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+protected:
+ /// Reference to our <WFMO_Reactor>.
+ ACE_WFMO_Reactor &wfmo_reactor_;
+
+ /// Maximum number of handles.
+ size_t max_size_;
+
+ /**
+ * Array of <ACE_HANDLEs> passed to <WaitForMultipleObjects>. This
+ * is not part of the structure as the handle array needs to be
+ * passed directly to <WaitForMultipleObjects>.
+ */
+ ACE_HANDLE *current_handles_;
+
+ /// Array of current entries in the table
+ Current_Info *current_info_;
+
+ /// A count of the number of active handles.
+ size_t max_handlep1_;
+
+ /// Information for entries to be added
+ To_Be_Added_Info *to_be_added_info_;
+
+ /// Number of records to be added
+ size_t handles_to_be_added_;
+
+ /// Currently suspended handles
+ Suspended_Info *current_suspended_info_;
+
+ /// Number of currently suspended handles
+ size_t suspended_handles_;
+
+ /// Number of records to be suspended
+ size_t handles_to_be_suspended_;
+
+ /// Number of records to be resumed
+ size_t handles_to_be_resumed_;
+
+ /// Number of records to be deleted
+ size_t handles_to_be_deleted_;
+
+};
+
+/**
+ * @class ACE_WFMO_Reactor_Notify
+ *
+ * @brief Unblock the <ACE_WFMO_Reactor> from its event loop, passing
+ * it an optional <ACE_Event_Handler> to dispatch.
+ *
+ * This implementation is necessary for cases where the
+ * <ACE_WFMO_Reactor> is run in a multi-threaded program. In
+ * this case, we need to be able to unblock
+ * <WaitForMultipleObjects> when updates occur other than in the
+ * main <ACE_WFMO_Reactor> thread. To do this, we signal an
+ * auto-reset event the <ACE_WFMO_Reactor> is listening on. If
+ * an <ACE_Event_Handler> and <ACE_Reactor_Mask> is passed to
+ * <notify>, the appropriate <handle_*> method is dispatched.
+ */
+class ACE_Export ACE_WFMO_Reactor_Notify : public ACE_Reactor_Notify
+{
+public:
+ /// Constructor
+ ACE_WFMO_Reactor_Notify (void);
+
+ /// Initialization. <timer_queue> is stored to call <gettimeofday>.
+ virtual int open (ACE_Reactor_Impl *wfmo_reactor,
+ ACE_Timer_Queue *timer_queue,
+ int disable_notify = 0);
+
+ /// No-op.
+ virtual int close (void);
+
+ /**
+ * Special trick to unblock <WaitForMultipleObjects> when updates
+ * occur. All we do is enqueue <event_handler> and <mask> onto the
+ * <ACE_Message_Queue> and wakeup the <WFMO_Reactor> by signaling
+ * its <ACE_Event> handle. The <ACE_Time_Value> indicates how long
+ * to blocking trying to notify the <WFMO_Reactor>. If <timeout> ==
+ * 0, the caller will block until action is possible, else will wait
+ * until the relative time specified in <timeout> elapses).
+ */
+ ssize_t notify (ACE_Event_Handler *event_handler = 0,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value *timeout = 0);
+
+ /// No-op.
+ virtual int dispatch_notifications (int &number_of_active_handles,
+ ACE_Handle_Set &rd_mask);
+
+ /// Returns a handle to the <ACE_Auto_Event>.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Returns the ACE_HANDLE of the notify pipe on which the reactor
+ /// is listening for notifications so that other threads can unblock
+ /// the <Reactor_Impl>
+ virtual ACE_HANDLE notify_handle (void);
+
+ /// Handle one of the notify call on the <handle>. This could be
+ /// because of a thread trying to unblock the <Reactor_Impl>
+ virtual int dispatch_notify (ACE_Notification_Buffer &buffer);
+
+ /// Verify whether the buffer has dispatchable info or not.
+ virtual int is_dispatchable (ACE_Notification_Buffer &buffer);
+
+ /// Read one of the notify call on the <handle> into the
+ /// <buffer>. This could be because of a thread trying to unblock
+ /// the <Reactor_Impl>
+ virtual int read_notify_pipe (ACE_HANDLE handle,
+ ACE_Notification_Buffer &buffer);
+
+ /**
+ * Set the maximum number of times that the
+ * <ACE_WFMO_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop. By default, this is set to
+ * -1, which means "iterate until the queue is empty." Setting this
+ * to a value like "1 or 2" will increase "fairness" (and thus
+ * prevent starvation) at the expense of slightly higher dispatching
+ * overhead.
+ */
+ void max_notify_iterations (int);
+
+ /**
+ * Get the maximum number of times that the
+ * <ACE_WFMO_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop.
+ */
+ int max_notify_iterations (void);
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. If <eh> == 0, all notifications for all
+ * handlers are removed (but not any notifications posted just to wake up
+ * the reactor itself). Returns the number of notifications purged.
+ * Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler *,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+private:
+ /// Pointer to the wfmo_reactor's timer queue.
+ ACE_Timer_Queue *timer_queue_;
+
+ /**
+ * Called when the notification event waited on by
+ * <ACE_WFMO_Reactor> is signaled. This dequeues all pending
+ * <ACE_Event_Handlers> and dispatches them.
+ */
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+
+ /// An auto event is used so that we can <signal> it to wakeup one
+ /// thread up (e.g., when the <notify> method is called).
+ ACE_Auto_Event wakeup_one_thread_;
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+// because Sun C++ 4.1 can't cope with this declaration:
+ ACE_Message_Queue<ACE_MT_SYNCH> message_queue_;
+#endif /* ACE_WIN32 */
+ // Message queue that keeps track of pending <ACE_Event_Handlers>.
+ // This queue must be thread-safe because it can be called by
+ // multiple threads of control.
+
+ /**
+ * Keeps track of the maximum number of times that the
+ * <ACE_WFMO_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop. By default, this is set to
+ * -1, which means "iterate until the queue is empty."
+ */
+ int max_notify_iterations_;
+};
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+/**
+ * @class ACE_WFMO_Reactor
+ *
+ * @brief An object oriented event demultiplexor and event handler
+ * WFMO_Reactor for Win32 WaitForMultipleObjects
+ *
+ * The ACE_WFMO_Reactor is an object-oriented event
+ * demultiplexor and event handler Reactor. The sources of
+ * events that the ACE_WFMO_Reactor waits for and dispatches
+ * includes I/O events, general Win32 synchronization events
+ * (such as mutexes, semaphores, threads, etc.) and timer
+ * events.
+ * Note that changes to the state of WFMO_Reactor are not
+ * instantaneous. Most changes (registration, removal,
+ * suspension, and resumption of handles, and changes in
+ * ownership) are made when the WFMO_Reactor reaches a stable
+ * state. Users should be careful, specially when removing
+ * handlers. This is because the WFMO_Reactor will call
+ * handle_close on the handler when it is finally removed and
+ * not when remove_handler is called. If the handler is not
+ * going to be around when the WFMO_Reactor calls
+ * <ACE_Event_Handler::handle_close>, use the DONT_CALL flag
+ * with <remove_handler>. Or else, dynamically allocate the
+ * handler, and then call "delete this" inside
+ * <ACE_Event_Handler::handle_close>.
+ */
+class ACE_Export ACE_WFMO_Reactor : public ACE_Reactor_Impl
+{
+public:
+ friend class ACE_WFMO_Reactor_Handler_Repository;
+ friend class ACE_WFMO_Reactor_Test;
+
+ enum
+ {
+ /// Default size of the WFMO_Reactor's handle table.
+ /**
+ * Two slots will be added to the <size> parameter in the
+ * constructor and open methods which will store handles used for
+ * internal management purposes.
+ */
+ DEFAULT_SIZE = MAXIMUM_WAIT_OBJECTS - 2
+ };
+
+ // = Initialization and termination methods.
+
+ /// Initialize <ACE_WFMO_Reactor> with the default size.
+ ACE_WFMO_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /**
+ * Initialize <ACE_WFMO_Reactor> with size <size>. <size> should
+ * not exceed <ACE_WFMO_Reactor::DEFAULT_SIZE>. Two slots will be
+ * added to the <size> parameter which will store handles used for
+ * internal management purposes.
+ */
+ ACE_WFMO_Reactor (size_t size,
+ int unused = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /**
+ * Initialize <ACE_WFMO_Reactor> with size <size>. <size> should
+ * not exceed <ACE_WFMO_Reactor::DEFAULT_SIZE>. Two slots will be
+ * added to the <size> parameter which will store handles used for
+ * internal management purposes.
+ */
+ virtual int open (size_t size = ACE_WFMO_Reactor::DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int disable_notify_pipe = 0,
+ ACE_Reactor_Notify * = 0);
+
+ /// Returns -1 (not used in this implementation);
+ virtual int current_info (ACE_HANDLE, size_t & /* size */);
+
+ /// Use a user specified signal handler instead.
+ virtual int set_sig_handler (ACE_Sig_Handler *signal_handler);
+
+ // = The following method is deprecated. Use <timer_queue> instead.
+ /// Set a user specified timer queue.
+ virtual int set_timer_queue (ACE_Timer_Queue *tq);
+
+ /// Set a user-specified timer queue.
+ /// Return the current <ACE_Timer_Queue>.
+ virtual int timer_queue (ACE_Timer_Queue *tq);
+ virtual ACE_Timer_Queue *timer_queue (void) const;
+
+ /// Close down the WFMO_Reactor and release all of its resources.
+ virtual int close (void);
+
+ /// Close down the WFMO_Reactor and release all of its resources.
+ virtual ~ACE_WFMO_Reactor (void);
+
+ // = Event loop drivers.
+
+ /**
+ * This method is not currently implemented. We recommend that you
+ * use handle_events (ACE_Time_Value::zero) to get basically the
+ * same effect, i.e., it won't block the caller if there are no events.
+ */
+ virtual int work_pending (const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
+
+ /**
+ * This event loop driver blocks for up to <max_wait_time> before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that <max_wait_time> can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * <WaitForMultipleObjects> is used as the demultiplexing call
+ *
+ * Returns the total number of I/O and timer <ACE_Event_Handler>s
+ * that were dispatched, 0 if the <max_wait_time> elapsed without
+ * dispatching any handlers, or -1 if an error occurs.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, TRUE is passed to
+ * <WaitForMultipleObjects> for the <bAlertable> option.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+ virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ /**
+ * This method is just like the one above, except the
+ * <max_wait_time> value is a reference and can therefore never be
+ * NULL.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, TRUE is passed to
+ * <WaitForMultipleObjects> for the <bAlertable> option.
+ */
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+ virtual int alertable_handle_events (ACE_Time_Value &max_wait_time);
+
+
+ // = Event handling control.
+
+ /**
+ * Return the status of Reactor. If this function returns 0, the reactor is
+ * actively handling events. If it returns non-zero, <handling_events> and
+ * <handle_alertable_events> return -1 immediately.
+ */
+ virtual int deactivated (void);
+
+ /**
+ * Control whether the Reactor will handle any more incoming events or not.
+ * If <do_stop> == 1, the Reactor will be disabled. By default, a reactor
+ * is in active state and can be deactivated/reactived as wish.
+ */
+ virtual void deactivate (int do_stop);
+
+ // = Register and remove Handlers.
+
+ /**
+ * Register an <ACE_Event_Handler> <event_handler>. Since no Event
+ * Mask is passed through this interface, it is assumed that the
+ * <handle> being passed in is an event handle and when the event
+ * becomes signaled, <WFMO_Reactor> will call handle_signal on
+ * <event_handler>. If <handle> == <ACE_INVALID_HANDLE> the
+ * <ACE_WFMO_Reactor> will call the <get_handle> method of
+ * <event_handler> to extract the underlying event handle.
+ */
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle = ACE_INVALID_HANDLE);
+
+ /**
+ * Register an <ACE_Event_Handler> <event_handle>. <mask> specifies
+ * the network events that the <event_handler> is interested in. If
+ * <io_handle> == <ACE_INVALID_HANDLE> the <ACE_WFMO_Reactor> will
+ * call the <get_handle> method of <event_handler> to extract the
+ * underlying I/O handle. If the <event_handle> ==
+ * <ACE_INVALID_HANDLE>, WFMO_Reactor will create an event for
+ * associating it with the I/O handle. When the <event_handle> is
+ * signalled, the appropriate <handle_*> callback will be invoked on
+ * the <Event_Handler>
+ */
+ virtual int register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * This is a simple version of the above <register_handler> method
+ * where the I/O handle is passed in and the event handle will
+ * always be created by <WFMO_Reactor>
+ */
+ virtual int register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * This is a simple version of the above <register_handler> method
+ * where the I/O handle will always come from <get_handle> on the
+ * <Event_Handler> and the event handle will always be created by
+ * <WFMO_Reactor>
+ */
+ virtual int register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register <event_handler> with all the <handles> in the
+ /// <Handle_Set>.
+ virtual int register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Register <new_sh> to handle the signal <signum> using the
+ * <new_disp>. Returns the <old_sh> that was previously registered
+ * (if any), along with the <old_disp> of the signal handler.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /// Registers <new_sh> to handle a set of signals <sigset> using the
+ /// <new_disp>.
+ virtual int register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0);
+
+ /**
+ * Removes <event_handler> from the <ACE_WFMO_Reactor>. Note that
+ * the <ACE_WFMO_Reactor> will call the <get_handle> method of
+ * <event_handler> to extract the underlying handle. If <mask> ==
+ * <ACE_Event_Handler::DONT_CALL> then the <handle_close> method of
+ * the <event_handler> is not invoked. Note that the <handle> can
+ * either be the <event_handle> or the <io_handle>
+ */
+ virtual int remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes <handle> from the <ACE_WFMO_Reactor>. If <mask> ==
+ * <ACE_Event_Handler::DONT_CALL> then the <handle_close> method of
+ * the <event_handler> is not invoked. Note that the <handle> can
+ * either be the <event_handle> or the <io_handle>
+ *
+ * For the case of I/O entries, this removes the <mask> binding of
+ * <Event_Handler> whose handle is <handle> from <WFMO_Reactor>. If
+ * there are no more bindings for this <event_handler> then it is
+ * removed from the WFMO_Reactor. For simple event entries, mask is
+ * mostly ignored and the <Event_Handler> is always removed from
+ * <WFMO_Reactor>
+ */
+ virtual int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes all the <mask> bindings for handles in the <handle_set>
+ * bind of <Event_Handler>. If there are no more bindings for any
+ * of these handles then they are removed from WFMO_Reactor.
+ */
+ virtual int remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask);
+
+ /**
+ * Remove the ACE_Event_Handler currently associated with <signum>.
+ * <sigkey> is ignored in this implementation since there is only
+ * one instance of a signal handler. Install the new disposition
+ * (if given) and return the previous disposition (if desired by the
+ * caller). Returns 0 on success and -1 if <signum> is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ /// Calls <remove_handler> for every signal in <sigset>.
+ virtual int remove_handler (const ACE_Sig_Set &sigset);
+
+ // = Suspend and resume Handlers.
+
+ /// Suspend <event_handler> temporarily. Use
+ /// <ACE_Event_Handler::get_handle> to get the handle.
+ virtual int suspend_handler (ACE_Event_Handler *event_handler);
+
+ /// Suspend <handle> temporarily.
+ virtual int suspend_handler (ACE_HANDLE handle);
+
+ /// Suspend all <handles> in handle set temporarily.
+ virtual int suspend_handler (const ACE_Handle_Set &handles);
+
+ /// Suspend all <handles> temporarily.
+ virtual int suspend_handlers (void);
+
+ /// Resume <event_handler>. Use <ACE_Event_Handler::get_handle> to
+ /// get the handle.
+ virtual int resume_handler (ACE_Event_Handler *event_handler);
+
+ /// Resume <handle>.
+ virtual int resume_handler (ACE_HANDLE handle);
+
+ /// Resume all <handles> in handle set.
+ virtual int resume_handler (const ACE_Handle_Set &handles);
+
+ /// Resume all <handles>.
+ virtual int resume_handlers (void);
+
+ /// Does the reactor allow the application to resume the handle on
+ /// its own ie. can it pass on the control of handle resumption to
+ /// the application. A positive value indicates that the handlers
+ /// are application resumable. A value of 0 indicates otherwise.
+ virtual int resumable_handler (void);
+
+ /**
+ * Return 1 if we any event associations were made by the reactor
+ * for the handles that it waits on, 0 otherwise. Since the
+ * WFMO_Reactor does use event associations, this function always
+ * return 1.
+ */
+ virtual int uses_event_associations (void);
+
+ // Timer management.
+
+ /**
+ * Schedule an ACE_Event_Handler that will expire after an amount
+ * of time. The return value of this method, a timer_id value,
+ * uniquely identifies the event_handler in the ACE_Reactor's
+ * internal list of timers.
+ * This timer_id value can be used to cancel the timer
+ * with the cancel_timer() call.
+ *
+ * @see cancel_timer()
+ * @see reset_timer_interval()
+ *
+ * @param event_handler event handler to schedule on reactor
+ * @param arg argument passed to the handle_timeout() method of event_handler
+ * @param delta time interval after which the timer will expire
+ * @param interval time interval after which the timer will be automatically rescheduled
+ * @return -1 on failure, a timer_id value on success
+ */
+ virtual long schedule_timer (ACE_Event_Handler *event_handler,
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+
+ /**
+ * Resets the interval of the timer represented by <timer_id> to
+ * <interval>, which is specified in relative time to the current
+ * <gettimeofday>. If <interval> is equal to
+ * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
+ * timer. Returns 0 if successful, -1 if not.
+ */
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ /// Cancel all Event_Handlers that match the address of
+ /// <event_handler>. Returns number of handler's cancelled.
+ virtual int cancel_timer (ACE_Event_Handler *event_handler,
+ int dont_call_handle_close = 1);
+
+ /**
+ * Cancel the single Event_Handler that matches the <timer_id> value
+ * (which was returned from the schedule method). If arg is
+ * non-NULL then it will be set to point to the ``magic cookie''
+ * argument passed in when the Event_Handler was registered. This
+ * makes it possible to free up the memory and avoid memory leaks.
+ * Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ * wasn't found.
+ */
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+ // = High-level Event_Handler scheduling operations
+
+ /**
+ * Add <masks_to_be_added> to the <event_handler>'s entry in
+ * WFMO_Reactor. <event_handler> must already have been registered
+ * with WFMO_Reactor.
+ */
+ virtual int schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /**
+ * Add <masks_to_be_added> to the <handle>'s entry in WFMO_Reactor.
+ * The Event_Handler associated with <handle> must already have been
+ * registered with WFMO_Reactor.
+ */
+ virtual int schedule_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_added);
+
+ /**
+ * Remove <masks_to_be_deleted> to the <handle>'s entry in
+ * WFMO_Reactor. The Event_Handler associated with <handle> must
+ * already have been registered with WFMO_Reactor.
+ */
+ virtual int cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_deleted);
+
+ /**
+ * Remove <masks_to_be_deleted> to the <handle>'s entry in
+ * WFMO_Reactor. The Event_Handler associated with <handle> must
+ * already have been registered with WFMO_Reactor.
+ */
+ virtual int cancel_wakeup (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks_to_be_deleted);
+
+ // = Notification methods.
+
+ /**
+ * Wakeup one <ACE_WFMO_Reactor> thread if it is currently blocked
+ * in <WaitForMultipleObjects>. The <ACE_Time_Value> indicates how
+ * long to blocking trying to notify the <WFMO_Reactor>. If
+ * <timeout> == 0, the caller will block until action is possible,
+ * else will wait until the relative time specified in <timeout>
+ * elapses).
+ */
+ virtual int notify (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK,
+ ACE_Time_Value * = 0);
+
+ /**
+ * Set the maximum number of times that the
+ * <ACE_WFMO_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop. By default, this is set to
+ * -1, which means "iterate until the queue is empty." Setting this
+ * to a value like "1 or 2" will increase "fairness" (and thus
+ * prevent starvation) at the expense of slightly higher dispatching
+ * overhead.
+ */
+ virtual void max_notify_iterations (int);
+
+ /**
+ * Get the maximum number of times that the
+ * <ACE_WFMO_Reactor_Notify::handle_input> method will iterate and
+ * dispatch the <ACE_Event_Handlers> that are passed in via the
+ * notify queue before breaking out of its
+ * <ACE_Message_Queue::dequeue> loop.
+ */
+ virtual int max_notify_iterations (void);
+
+ /**
+ * Purge any notifications pending in this reactor for the specified
+ * <ACE_Event_Handler> object. Returns the number of notifications
+ * purged. Returns -1 on error.
+ */
+ virtual int purge_pending_notifications (ACE_Event_Handler * = 0,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ // = Assorted helper methods.
+
+ /**
+ * Check to see if <handle> is associated with a valid Event_Handler
+ * bound to <mask>. Return the <event_handler> associated with this
+ * <handler> if <event_handler> != 0.
+ */
+ virtual int handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler = 0);
+
+ /**
+ * Check to see if <signum> is associated with a valid Event_Handler
+ * bound to a signal. Return the <event_handler> associated with
+ * this <handler> if <event_handler> != 0.
+ */
+ virtual int handler (int signum,
+ ACE_Event_Handler ** = 0);
+
+ /// Returns true if WFMO_Reactor has been successfully initialized, else
+ /// false.
+ virtual int initialized (void);
+
+ /// Returns the current size of the WFMO_Reactor's internal
+ /// descriptor table.
+ virtual size_t size (void) const;
+
+ /// Returns a reference to the WFMO_Reactor's internal lock.
+ virtual ACE_Lock &lock (void);
+
+ /// Wake up all threads in WaitForMultipleObjects so that they can
+ /// reconsult the handle set
+ virtual void wakeup_all_threads (void);
+
+ /**
+ * Transfers ownership of the WFMO_Reactor to the <new_owner>. The
+ * transfer will not complete until all threads are ready (just like
+ * the handle set).
+ */
+ virtual int owner (ACE_thread_t new_owner, ACE_thread_t *old_owner = 0);
+
+ /// Return the ID of the "owner" thread.
+ virtual int owner (ACE_thread_t *owner);
+
+ /// Get the existing restart value.
+ virtual int restart (void);
+
+ /// Set a new value for restart and return the original value.
+ virtual int restart (int r);
+
+ /// Not implemented
+ virtual void requeue_position (int);
+
+ /// Not implemented
+ virtual int requeue_position (void);
+
+ // = Low-level wait_set mask manipulation methods.
+
+ /**
+ * Modify <masks> of the <event_handler>'s entry in WFMO_Reactor
+ * depending upon <operation>. <event_handler> must already have
+ * been registered with WFMO_Reactor.
+ */
+ virtual int mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks,
+ int operation);
+
+ /**
+ * Modify <masks> of the <handle>'s entry in WFMO_Reactor depending
+ * upon <operation>. <handle> must already have been registered
+ * with WFMO_Reactor.
+ */
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask masks,
+ int ops);
+
+ // = Low-level ready_set mask manipulation methods.
+
+ /// Not implemented
+ virtual int ready_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// Not implemented
+ virtual int ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask,
+ int ops);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+protected:
+ /// Registration workhorse
+ virtual int register_handler_i (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask);
+
+ /// Event handling workhorse
+ virtual int event_handling (ACE_Time_Value *max_wait_time = 0,
+ int alertable = 0);
+
+ /// Bit masking workhorse
+ virtual int mask_ops_i (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask masks,
+ int operation);
+
+ /// Return the ID of the "owner" thread. Does not do any locking.
+ virtual ACE_thread_t owner_i (void);
+
+ /// Check to see if it is ok to enter <::WaitForMultipleObjects>.
+ virtual int ok_to_wait (ACE_Time_Value *max_wait_time,
+ int alertable);
+
+ /// Wait for timer and I/O events to occur.
+ virtual int wait_for_multiple_events (int timeout,
+ int alertable);
+
+ /// Check for activity on remaining handles.
+ virtual DWORD poll_remaining_handles (size_t slot);
+
+ /// Expire timers. Only the owner thread does useful stuff in this
+ /// function.
+ virtual int expire_timers (void);
+
+ /// Dispatches the timers and I/O handlers.
+ virtual int dispatch (int wait_status);
+
+ /// Protect against structured exceptions caused by user code when
+ /// dispatching handles
+ virtual int safe_dispatch (int wait_status);
+
+ /**
+ * Dispatches any active handles from handles_[<slot>] to
+ * handles_[active_handles_] using <WaitForMultipleObjects> to poll
+ * through our handle set looking for active handles.
+ */
+ virtual int dispatch_handles (size_t slot);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int dispatch_handler (size_t slot,
+ size_t max_handlep1);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int simple_dispatch_handler (int slot,
+ ACE_HANDLE event_handle);
+
+ /// Dispatches a single handler. Returns 0 on success, -1 if the
+ /// handler was removed.
+ virtual int complex_dispatch_handler (int slot,
+ ACE_HANDLE event_handle);
+
+ /// Dispatches window messages. Noop for WFMO_Reactor.
+ virtual int dispatch_window_messages (void);
+
+ virtual ACE_Reactor_Mask upcall (ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ WSANETWORKEVENTS &events);
+
+ /// Used to caluculate the next timeout
+ virtual int calculate_timeout (ACE_Time_Value *time);
+
+ /// Update the state of the handler repository
+ virtual int update_state (void);
+
+ /// Check to see if we have a new owner
+ virtual int new_owner (void);
+
+ /// Set owner to new owner
+ virtual int change_owner (void);
+
+ /// Handle signals without requiring global/static variables.
+ ACE_Sig_Handler *signal_handler_;
+
+ /// Keeps track of whether we should delete the signal handler (if we
+ /// didn't create it, then we don't delete it).
+ int delete_signal_handler_;
+
+ /// Defined as a pointer to allow overriding by derived classes...
+ ACE_Timer_Queue *timer_queue_;
+
+ /// Keeps track of whether we should delete the timer queue (if we
+ /// didn't create it, then we don't delete it).
+ int delete_timer_queue_;
+
+ /// Keeps track of whether we should delete the handler repository
+ int delete_handler_rep_;
+
+ /// Used when <notify> is called.
+ ACE_Reactor_Notify *notify_handler_;
+
+ /// Keeps track of whether we should delete the notify handler.
+ int delete_notify_handler_;
+
+ /**
+ * Synchronization for the ACE_WFMO_Reactor.
+ *
+ * A Process Mutex is used here because of two reasons:
+ * (a) The implementation of ACE_Thread_Mutex uses CriticalSections
+ * CriticalSections are not waitable using ::WaitForMultipleObjects
+ * (b) This is really not a process mutex because it is not
+ * named. No other process can use this mutex.
+ */
+ ACE_Process_Mutex lock_;
+
+ /// Adapter used to return internal lock to outside world.
+ ACE_Lock_Adapter<ACE_Process_Mutex> lock_adapter_;
+
+ /// Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s.
+ ACE_WFMO_Reactor_Handler_Repository handler_rep_;
+
+ /// A manual event used to block threads from proceeding into
+ /// WaitForMultipleObjects
+ ACE_Manual_Event ok_to_wait_;
+
+ /**
+ * A manual event is used so that we can wake everyone up (e.g.,
+ * when <ACE_Event_Handlers> are bounded and unbound from the
+ * handler repository).
+ */
+ ACE_Manual_Event wakeup_all_threads_;
+
+ /// Used when <wakeup_all_threads_> is signaled
+ ACE_Wakeup_All_Threads_Handler wakeup_all_threads_handler_;
+
+ /// The changing thread waits on this event, till all threads are not
+ /// active anymore
+ ACE_Auto_Event waiting_to_change_state_;
+
+ /// Count of currently active threads
+ size_t active_threads_;
+
+ /**
+ * The thread which is "owner" of the WFMO_Reactor. The owner
+ * concept is used because we don't want multiple threads to try to
+ * expire timers. Therefore the "owner" thread is the only one
+ * allowed to expire timers. Also, the owner thread is the only
+ * thread which waits on the notify handle. Note that the ownership
+ * can be transferred.
+ */
+ ACE_thread_t owner_;
+
+ /// The owner to be of the WFMO_Reactor
+ ACE_thread_t new_owner_;
+
+ /// This is the thread which is responsible for the changing the
+ /// state of the <WFMO_Reactor> handle set
+ ACE_thread_t change_state_thread_;
+
+ /// This is an array of ACE_HANDLEs which keep track of the <lock_>
+ /// and <ok_to_wait_> handles
+ ACE_HANDLE atomic_wait_array_ [2];
+
+ /// This flag is used to keep track of whether we are already closed.
+ int open_for_business_;
+
+ /// This flag is used to keep track of whether we are actively handling
+ /// events or not.
+ sig_atomic_t deactivated_;
+
+private:
+ /// Deny access since member-wise won't work...
+ ACE_WFMO_Reactor (const ACE_WFMO_Reactor &);
+ ACE_WFMO_Reactor &operator = (const ACE_WFMO_Reactor &);
+};
+
+#endif /* ACE_WIN32 */
+
+#if defined (__ACE_INLINE__)
+#include "ace/WFMO_Reactor.i"
+#endif /* __ACE_INLINE__ */
+#include "ace/post.h"
+#endif /* ACE_WFMO_REACTOR_H */
diff --git a/ace/Demux/WFMO_Reactor.i b/ace/Demux/WFMO_Reactor.i
new file mode 100644
index 00000000000..d2a8481f886
--- /dev/null
+++ b/ace/Demux/WFMO_Reactor.i
@@ -0,0 +1,1131 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Handle_Set.h"
+#include "ace/Reactor.h"
+/************************************************************/
+
+ACE_INLINE int
+ACE_Wakeup_All_Threads_Handler::handle_signal (int signum,
+ siginfo_t *siginfo,
+ ucontext_t *)
+{
+ ACE_UNUSED_ARG (signum);
+ ACE_UNUSED_ARG (siginfo);
+
+ // This will get called when <WFMO_Reactor->wakeup_all_threads_> event
+ // is signaled. There is nothing to be done here.
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%t) waking up to get updated handle set info\n")));
+ return 0;
+}
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+/************************************************************/
+
+ACE_INLINE
+ACE_WFMO_Reactor_Handler_Repository::Common_Info::Common_Info (void)
+ : io_entry_ (0),
+ event_handler_ (0),
+ io_handle_ (ACE_INVALID_HANDLE),
+ network_events_ (0),
+ delete_event_ (0),
+ delete_entry_ (0),
+ close_masks_ (ACE_Event_Handler::NULL_MASK)
+{
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Common_Info::reset (void)
+{
+ this->event_handler_ = 0;
+ this->io_entry_ = 0;
+ this->io_handle_ = ACE_INVALID_HANDLE;
+ this->network_events_ = 0;
+ this->delete_event_ = 0;
+ this->delete_entry_ = 0;
+ this->close_masks_ = ACE_Event_Handler::NULL_MASK;
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Common_Info::set (int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry,
+ ACE_Reactor_Mask close_masks)
+{
+ this->event_handler_ = event_handler;
+ this->io_entry_ = io_entry;
+ this->io_handle_ = io_handle;
+ this->network_events_ = network_events;
+ this->delete_event_ = delete_event;
+ this->delete_entry_ = delete_entry;
+ this->close_masks_ = close_masks;
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Common_Info::set (Common_Info &common_info)
+{
+ *this = common_info;
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Common_Info::dump (void) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::Common_Info::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("I/O Entry = %d\n"),
+ this->io_entry_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Event Handler = %d\n"),
+ this->event_handler_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("I/O Handle = %d\n"),
+ this->io_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Network Events = %d\n"),
+ this->network_events_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Delete Event = %d\n"),
+ this->delete_event_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Delete Entry = %d\n"),
+ this->delete_entry_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Close Masks = %d\n"),
+ this->close_masks_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+/************************************************************/
+
+ACE_INLINE
+ACE_WFMO_Reactor_Handler_Repository::Current_Info::Current_Info (void)
+ : suspend_entry_ (0)
+{
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Current_Info::set (int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry,
+ ACE_Reactor_Mask close_masks,
+ int suspend_entry)
+{
+ this->suspend_entry_ = suspend_entry;
+ Common_Info::set (io_entry,
+ event_handler,
+ io_handle,
+ network_events,
+ delete_event,
+ delete_entry,
+ close_masks);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Current_Info::set (Common_Info &common_info,
+ int suspend_entry)
+{
+ this->suspend_entry_ = suspend_entry;
+ Common_Info::set (common_info);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Current_Info::reset (void)
+{
+ this->suspend_entry_ = 0;
+ Common_Info::reset ();
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Current_Info::dump (ACE_HANDLE event_handle) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::Current_Info::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ Common_Info::dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Event Handle = %d\n"),
+ event_handle));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Suspend Entry = %d\n"),
+ this->suspend_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+/************************************************************/
+
+ACE_INLINE
+ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::To_Be_Added_Info (void)
+ : event_handle_ (ACE_INVALID_HANDLE),
+ suspend_entry_ (0)
+{
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::set (ACE_HANDLE event_handle,
+ int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry,
+ ACE_Reactor_Mask close_masks,
+ int suspend_entry)
+{
+ this->event_handle_ = event_handle;
+ this->suspend_entry_ = suspend_entry;
+ Common_Info::set (io_entry,
+ event_handler,
+ io_handle,
+ network_events,
+ delete_event,
+ delete_entry,
+ close_masks);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::set (ACE_HANDLE event_handle,
+ Common_Info &common_info,
+ int suspend_entry)
+{
+ this->event_handle_ = event_handle;
+ this->suspend_entry_ = suspend_entry;
+ Common_Info::set (common_info);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::reset (void)
+{
+ this->event_handle_ = ACE_INVALID_HANDLE;
+ this->suspend_entry_ = 0;
+ Common_Info::reset ();
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::dump (void) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::To_Be_Added_Info::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ Common_Info::dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Event Handle = %d\n"),
+ this->event_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Suspend Entry = %d\n"),
+ this->suspend_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+/************************************************************/
+
+ACE_INLINE
+ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::Suspended_Info (void)
+ : event_handle_ (ACE_INVALID_HANDLE),
+ resume_entry_ (0)
+{
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::reset (void)
+{
+ this->event_handle_ = ACE_INVALID_HANDLE;
+ this->resume_entry_ = 0;
+ Common_Info::reset ();
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::set (ACE_HANDLE event_handle,
+ int io_entry,
+ ACE_Event_Handler *event_handler,
+ ACE_HANDLE io_handle,
+ long network_events,
+ int delete_event,
+ int delete_entry,
+ ACE_Reactor_Mask close_masks,
+ int resume_entry)
+{
+ this->event_handle_ = event_handle;
+ this->resume_entry_ = resume_entry;
+ Common_Info::set (io_entry,
+ event_handler,
+ io_handle,
+ network_events,
+ delete_event,
+ delete_entry,
+ close_masks);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::set (ACE_HANDLE event_handle,
+ Common_Info &common_info,
+ int resume_entry)
+{
+ this->event_handle_ = event_handle;
+ this->resume_entry_ = resume_entry;
+ Common_Info::set (common_info);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::dump (void) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::Suspended_Info::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ Common_Info::dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Event Handle = %d\n"),
+ this->event_handle_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Resume Entry = %d\n"),
+ this->resume_entry_));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+/************************************************************/
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::close (void)
+{
+ // Let all the handlers know that the <WFMO_Reactor> is closing down
+ this->unbind_all ();
+
+ return 0;
+}
+
+ACE_INLINE ACE_HANDLE *
+ACE_WFMO_Reactor_Handler_Repository::handles (void) const
+{
+ // This code is probably too subtle to be useful in the long run...
+ // The basic idea is that all threads wait on all user handles plus
+ // the <wakeup_all_threads_> handle. The owner thread additional
+ // waits on the <notify_> handle. This is to ensure that only the
+ // <owner_> thread get to expire timers and handle event on the
+ // notify pipe.
+ if (ACE_Thread::self () == this->wfmo_reactor_.owner_i ())
+ return this->current_handles_;
+ else
+ return this->current_handles_ + 1;
+}
+
+ACE_INLINE ACE_WFMO_Reactor_Handler_Repository::Current_Info *
+ACE_WFMO_Reactor_Handler_Repository::current_info (void) const
+{
+ if (ACE_Thread::self () == this->wfmo_reactor_.owner_i ())
+ return this->current_info_;
+ else
+ return this->current_info_ + 1;
+}
+
+ACE_INLINE size_t
+ACE_WFMO_Reactor_Handler_Repository::max_handlep1 (void) const
+{
+ if (ACE_Thread::self () == this->wfmo_reactor_.owner_i ())
+ return this->max_handlep1_;
+ else
+ return this->max_handlep1_ - 1;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::scheduled_for_deletion (size_t slot) const
+{
+ if (ACE_Thread::self () == this->wfmo_reactor_.owner_i ())
+ return this->current_info_[slot].delete_entry_ == 1;
+ else
+ return this->current_info_[slot + 1].delete_entry_ == 1;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::invalid_handle (ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_WFMO_Reactor_Handler_Repository::invalid_handle");
+ // It's too expensive to perform more exhaustive validity checks on
+ // Win32 due to the way that they implement SOCKET HANDLEs.
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::changes_required (void)
+{
+ // Check if handles have be scheduled for additions or removal
+ return this->handles_to_be_added_ > 0
+ || this->handles_to_be_deleted_ > 0
+ || this->handles_to_be_suspended_ > 0
+ || this->handles_to_be_resumed_ > 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::make_changes (void)
+{
+ // This method must ONLY be called by the
+ // <WFMO_Reactor->change_state_thread_>. We therefore assume that
+ // there will be no contention for this method and hence no guards
+ // are neccessary.
+
+ // Deletions and suspensions in current_info_
+ this->make_changes_in_current_infos ();
+
+ // Deletions and resumptions in current_suspended_info_
+ this->make_changes_in_suspension_infos ();
+
+ // Deletions in to_be_added_info_, or transfers to current_info_ or
+ // current_suspended_info_ from to_be_added_info_
+ this->make_changes_in_to_be_added_infos ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::unbind (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ if (this->invalid_handle (handle))
+ return -1;
+
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->wfmo_reactor_.lock_, -1);
+
+ int changes_required = 0;
+ int result = this->unbind_i (handle,
+ mask,
+ changes_required);
+
+ if (changes_required)
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wfmo_reactor_.wakeup_all_threads ();
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::reset_timer_interval");
+
+ long result = this->timer_queue_->reset_interval
+ (timer_id,
+ interval);
+
+ // Wakeup the owner thread so that it gets the latest timer values
+ this->notify ();
+
+ return result;
+}
+
+ACE_INLINE long
+ACE_WFMO_Reactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::schedule_timer");
+
+ long result = this->timer_queue_->schedule
+ (handler,
+ arg,
+ timer_queue_->gettimeofday () + delay_time,
+ interval);
+
+ // Wakeup the owner thread so that it gets the latest timer values
+ this->notify ();
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::cancel_timer");
+ return this->timer_queue_->cancel (handler, dont_call_handle_close);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_WFMO_Reactor::cancel_timer");
+ return this->timer_queue_->cancel (timer_id, arg, dont_call_handle_close);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (ACE_Event_Handler *event_handler,
+ ACE_HANDLE event_handle)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->handler_rep_.bind_i (0,
+ event_handler,
+ 0,
+ ACE_INVALID_HANDLE,
+ event_handle,
+ 0);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->register_handler_i (ACE_INVALID_HANDLE,
+ ACE_INVALID_HANDLE,
+ event_handler,
+ mask);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->register_handler_i (ACE_INVALID_HANDLE,
+ io_handle,
+ event_handler,
+ mask);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (ACE_HANDLE event_handle,
+ ACE_HANDLE io_handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->register_handler_i (event_handle,
+ io_handle,
+ event_handler,
+ mask);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->register_handler_i (h,
+ ACE_INVALID_HANDLE,
+ handler,
+ mask) == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::schedule_wakeup (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask masks_to_be_added)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->mask_ops_i (io_handle,
+ masks_to_be_added,
+ ACE_Reactor::ADD_MASK);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::schedule_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_added)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->mask_ops_i (event_handler->get_handle (),
+ masks_to_be_added,
+ ACE_Reactor::ADD_MASK);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::cancel_wakeup (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask masks_to_be_removed)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->mask_ops_i (io_handle,
+ masks_to_be_removed,
+ ACE_Reactor::CLR_MASK);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::cancel_wakeup (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask masks_to_be_removed)
+{
+ // This GUARD is necessary since we are updating shared state.
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ return this->mask_ops_i (event_handler->get_handle (),
+ masks_to_be_removed,
+ ACE_Reactor::CLR_MASK);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::remove_handler (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask)
+{
+ return this->handler_rep_.unbind (event_handler->get_handle (),
+ mask);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ return this->handler_rep_.unbind (handle,
+ mask);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::remove_handler (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+ int changes_required = 0;
+
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->handler_rep_.unbind_i (h,
+ mask,
+ changes_required) == -1)
+ return -1;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::suspend_handler (ACE_HANDLE handle)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ int changes_required = 0;
+ int result =
+ this->handler_rep_.suspend_handler_i (handle,
+ changes_required);
+
+ if (changes_required)
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::suspend_handler (ACE_Event_Handler *event_handler)
+{
+ return this->suspend_handler (event_handler->get_handle ());
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::suspend_handler (const ACE_Handle_Set &handles)
+{
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+ int changes_required = 0;
+
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->handler_rep_.suspend_handler_i (h,
+ changes_required) == -1)
+ return -1;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::suspend_handlers (void)
+{
+ int error = 0;
+ int result = 0;
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ // First suspend all current handles
+ int changes_required = 0;
+
+ for (size_t i = 0;
+ i < this->handler_rep_.max_handlep1_ && error == 0;
+ i++)
+ {
+ result =
+ this->handler_rep_.suspend_handler_i (this->handler_rep_.current_handles_[i],
+ changes_required);
+ if (result == -1)
+ error = 1;
+ }
+
+ if (!error)
+ // Then suspend all to_be_added_handles
+ for (size_t i = 0;
+ i < this->handler_rep_.handles_to_be_added_;
+ i++)
+ this->handler_rep_.to_be_added_info_[i].suspend_entry_ = 1;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return error ? -1 : 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::resume_handler (ACE_HANDLE handle)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ int changes_required = 0;
+ int result =
+ this->handler_rep_.resume_handler_i (handle,
+ changes_required);
+
+ if (changes_required)
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::resume_handler (ACE_Event_Handler *event_handler)
+{
+ return this->resume_handler (event_handler->get_handle ());
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::resume_handler (const ACE_Handle_Set &handles)
+{
+ ACE_Handle_Set_Iterator handle_iter (handles);
+ ACE_HANDLE h;
+ int changes_required = 0;
+
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ if (this->handler_rep_.resume_handler_i (h,
+ changes_required) == -1)
+ return -1;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::resume_handlers (void)
+{
+ int error = 0;
+ int result = 0;
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+
+ int changes_required = 0;
+ for (size_t i = 0;
+ i < this->handler_rep_.suspended_handles_ && error == 0;
+ i++)
+ {
+ result =
+ this->handler_rep_.resume_handler_i (this->handler_rep_.current_suspended_info_[i].event_handle_,
+ changes_required);
+ if (result == -1)
+ error = 1;
+ }
+
+ if (!error)
+ // Then resume all to_be_added_handles
+ for (size_t i = 0;
+ i < this->handler_rep_.handles_to_be_added_;
+ i++)
+ this->handler_rep_.to_be_added_info_[i].suspend_entry_ = 0;
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the handle set
+ this->wakeup_all_threads ();
+
+ return error ? -1 : 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::uses_event_associations (void)
+{
+ // Since the WFMO_Reactor does use event associations, this function
+ // always return 1.
+ return 1;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::handle_events (ACE_Time_Value &how_long)
+{
+ return this->event_handling (&how_long, FALSE);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::alertable_handle_events (ACE_Time_Value &how_long)
+{
+ return this->event_handling (&how_long, TRUE);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::handle_events (ACE_Time_Value *how_long)
+{
+ return this->event_handling (how_long, FALSE);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::alertable_handle_events (ACE_Time_Value *how_long)
+{
+ return this->event_handling (how_long, TRUE);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::deactivated (void)
+{
+ return this->deactivated_;
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor::deactivate (int do_stop)
+{
+ this->deactivated_ = do_stop;
+ this->wakeup_all_threads ();
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::owner (ACE_thread_t *t)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1);
+ *t = this->owner_i ();
+ return 0;
+}
+
+ACE_INLINE ACE_thread_t
+ACE_WFMO_Reactor::owner_i (void)
+{
+ return this->owner_;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::owner (ACE_thread_t new_owner, ACE_thread_t *old_owner)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, monitor, this->lock_, -1);
+ this->new_owner_ = new_owner;
+
+ if (old_owner != 0)
+ *old_owner = this->owner_i ();
+
+ // Wake up all threads in WaitForMultipleObjects so that they can
+ // reconsult the new owner responsibilities
+ this->wakeup_all_threads ();
+
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::new_owner (void)
+{
+ return this->new_owner_ != ACE_thread_t (0);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::change_owner (void)
+{
+ this->owner_ = this->new_owner_;
+ this->new_owner_ = ACE_thread_t (0);
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::safe_dispatch (int wait_status)
+{
+ int result = -1;
+ ACE_SEH_TRY
+ {
+ result = this->dispatch (wait_status);
+ }
+ ACE_SEH_FINALLY
+ {
+ this->update_state ();
+ }
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::dispatch_window_messages (void)
+{
+ return 0;
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor::wakeup_all_threads (void)
+{
+ this->wakeup_all_threads_.signal ();
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::notify (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ ACE_Time_Value *timeout)
+{
+ return this->notify_handler_->notify (event_handler, mask, timeout);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **old_sh,
+ ACE_Sig_Action *old_disp)
+{
+ return this->signal_handler_->register_handler (signum,
+ new_sh, new_disp,
+ old_sh, old_disp);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::register_handler (const ACE_Sig_Set &sigset,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp)
+{
+ int result = 0;
+
+#if (ACE_NSIG > 0)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (sigset.is_member (s)
+ && this->signal_handler_->register_handler (s,
+ new_sh,
+ new_disp) == -1)
+ result = -1;
+#else
+ ACE_UNUSED_ARG (sigset);
+ ACE_UNUSED_ARG (new_sh);
+ ACE_UNUSED_ARG (new_disp);
+#endif /* ACE_NSIG */
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int sigkey)
+{
+ return this->signal_handler_->remove_handler (signum,
+ new_disp,
+ old_disp,
+ sigkey);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::remove_handler (const ACE_Sig_Set &sigset)
+{
+ int result = 0;
+
+#if (ACE_NSIG > 0)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (sigset.is_member (s)
+ && this->signal_handler_->remove_handler (s) == -1)
+ result = -1;
+#else
+ ACE_UNUSED_ARG (sigset);
+#endif /* ACE_NSIG */
+
+ return result;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::handler (int signum, ACE_Event_Handler **eh)
+{
+ ACE_Event_Handler *handler =
+ this->signal_handler_->handler (signum);
+
+ if (handler == 0)
+ return -1;
+ else if (eh != 0 && *eh != 0)
+ *eh = handler;
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::mask_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int operation)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, monitor, this->lock_, -1);
+
+ return this->mask_ops_i (event_handler->get_handle (),
+ mask,
+ operation);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::mask_ops (ACE_HANDLE io_handle,
+ ACE_Reactor_Mask mask,
+ int operation)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, monitor, this->lock_, -1);
+
+ return this->mask_ops_i (io_handle,
+ mask,
+ operation);
+}
+
+ACE_INLINE void
+ACE_WFMO_Reactor::requeue_position (int)
+{
+ // Not implemented
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::requeue_position (void)
+{
+ // Don't have an implementation for this yet...
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::restart (void)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::restart (int)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::ready_ops (ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ // Don't have an implementation for this yet...
+ ACE_UNUSED_ARG (event_handler);
+ ACE_UNUSED_ARG (mask);
+ ACE_UNUSED_ARG (ops);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::ready_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask,
+ int ops)
+{
+ // Don't have an implementation for this yet...
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (ops);
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Event_Handler **event_handler)
+{
+ return this->handler_rep_.handler (handle,
+ mask,
+ event_handler);
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor::initialized (void)
+{
+ return this->open_for_business_;
+}
+
+ACE_INLINE ACE_Lock &
+ACE_WFMO_Reactor::lock (void)
+{
+ return this->lock_adapter_;
+}
+
+ACE_INLINE size_t
+ACE_WFMO_Reactor::size (void) const
+{
+ // Size of repository minus the 2 used for internal purposes
+ return this->handler_rep_.max_size_ - 2;
+}
+#else
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::changes_required (void)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_WFMO_Reactor_Handler_Repository::make_changes (void)
+{
+ return 0;
+}
+
+ACE_INLINE
+ACE_WFMO_Reactor_Handler_Repository::~ACE_WFMO_Reactor_Handler_Repository (void)
+{
+}
+
+#endif /* ACE_WIN32 */
diff --git a/ace/Demux/WIN32_Proactor.cpp b/ace/Demux/WIN32_Proactor.cpp
new file mode 100644
index 00000000000..9f0ccfccc2c
--- /dev/null
+++ b/ace/Demux/WIN32_Proactor.cpp
@@ -0,0 +1,736 @@
+// $Id$
+
+// ACE_RCSID(ace, Proactor, "$Id$")
+
+#include "ace/WIN32_Proactor.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+// WIN implemenatation of the Proactor.
+
+#include "ace/Log_Msg.h"
+#include "ace/Object_Manager.h"
+
+class ACE_Export ACE_WIN32_Wakeup_Completion : public ACE_WIN32_Asynch_Result
+{
+ // = TITLE
+ // This is result object is used by the <end_event_loop> of the
+ // ACE_Proactor interface to wake up all the threads blocking
+ // for completions.
+
+public:
+ ACE_WIN32_Wakeup_Completion (ACE_Handler &handler,
+ const void *act = 0,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = ACE_SIGRTMIN);
+ // Constructor.
+
+ virtual ~ACE_WIN32_Wakeup_Completion (void);
+ // Destructor.
+
+
+ virtual void complete (u_long bytes_transferred = 0,
+ int success = 1,
+ const void *completion_key = 0,
+ u_long error = 0);
+ // This method calls the <handler>'s <handle_wakeup> method.
+};
+
+ACE_WIN32_Proactor::ACE_WIN32_Proactor (size_t number_of_threads,
+ int used_with_reactor_event_loop)
+ : completion_port_ (0),
+ // This *MUST* be 0, *NOT* ACE_INVALID_HANDLE !!!
+ number_of_threads_ (number_of_threads),
+ used_with_reactor_event_loop_ (used_with_reactor_event_loop)
+{
+ // Create the completion port.
+ this->completion_port_ = ::CreateIoCompletionPort (INVALID_HANDLE_VALUE,
+ 0,
+ 0,
+ this->number_of_threads_);
+ if (this->completion_port_ == 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("CreateIoCompletionPort")));
+}
+
+ACE_WIN32_Proactor::~ACE_WIN32_Proactor (void)
+{
+ this->close ();
+}
+
+int
+ACE_WIN32_Proactor::close (void)
+{
+ // Close the completion port
+ if (this->completion_port_ != 0)
+ {
+ // To avoid memory leaks we should delete all results from queue.
+
+ for (;;)
+ {
+ ACE_OVERLAPPED *overlapped = 0;
+ u_long bytes_transferred = 0;
+ u_long completion_key = 0;
+
+ // Get the next asynchronous operation that completes
+ BOOL res = ::GetQueuedCompletionStatus
+ (this->completion_port_,
+ &bytes_transferred,
+ &completion_key,
+ &overlapped,
+ 0); // poll
+
+ if (overlapped == 0)
+ break;
+
+ ACE_WIN32_Asynch_Result *asynch_result =
+ (ACE_WIN32_Asynch_Result *) overlapped;
+
+ delete asynch_result;
+ }
+
+ int result = ACE_OS::close (this->completion_port_);
+ this->completion_port_ = 0;
+ return result;
+ }
+
+ return 0;
+}
+
+int
+ACE_WIN32_Proactor::register_handle (ACE_HANDLE handle,
+ const void *completion_key)
+{
+ // No locking is needed here as no state changes.
+ ACE_HANDLE cp = ::CreateIoCompletionPort (handle,
+ this->completion_port_,
+ (u_long) completion_key,
+ this->number_of_threads_);
+ if (cp == 0)
+ {
+ ACE_OS::set_errno_to_last_error ();
+ // If errno == ERROR_INVALID_PARAMETER, then this handle was
+ // already registered.
+ if (errno != ERROR_INVALID_PARAMETER)
+ {
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("CreateIoCompletionPort")));
+ }
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ACE_Asynch_Read_Stream_Impl *
+ACE_WIN32_Proactor::create_asynch_read_stream (void)
+{
+ ACE_Asynch_Read_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Stream_Impl *
+ACE_WIN32_Proactor::create_asynch_write_stream (void)
+{
+ ACE_Asynch_Write_Stream_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_Stream (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Dgram_Impl *
+ACE_WIN32_Proactor::create_asynch_read_dgram (void)
+{
+ ACE_Asynch_Read_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_Dgram (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Dgram_Impl *
+ACE_WIN32_Proactor::create_asynch_write_dgram (void)
+{
+ ACE_Asynch_Write_Dgram_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_Dgram (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_File_Impl *
+ACE_WIN32_Proactor::create_asynch_read_file (void)
+{
+ ACE_Asynch_Read_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_File_Impl *
+ACE_WIN32_Proactor::create_asynch_write_file (void)
+{
+ ACE_Asynch_Write_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Accept_Impl *
+ACE_WIN32_Proactor::create_asynch_accept (void)
+{
+ ACE_Asynch_Accept_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Accept (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Impl *
+ACE_WIN32_Proactor::create_asynch_transmit_file (void)
+{
+ ACE_Asynch_Transmit_File_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Transmit_File (this),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Stream_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Read_Stream_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Stream_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Write_Stream_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_Stream_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_File_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Read_File_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_File_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_File_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Write_File_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_File_Result (handler,
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ offset,
+ offset_high,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Read_Dgram_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event ,
+ int priority ,
+ int signal_number)
+{
+ ACE_Asynch_Read_Dgram_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Read_Dgram_Result (handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ flags,
+ protocol_family,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Write_Dgram_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ const void* act,
+ ACE_HANDLE event ,
+ int priority ,
+ int signal_number)
+{
+ ACE_Asynch_Write_Dgram_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Write_Dgram_Result(handler,
+ handle,
+ message_block,
+ bytes_to_read,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Accept_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Accept_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Accept_Result (handler,
+ listen_handle,
+ accept_handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Transmit_File_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Transmit_File_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Transmit_File_Result (handler,
+ socket,
+ file,
+ header_and_trailer,
+ bytes_to_write,
+ offset,
+ offset_high,
+ bytes_per_send,
+ flags,
+ act,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+ACE_Asynch_Result_Impl *
+ACE_WIN32_Proactor::create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+{
+ ACE_Asynch_Result_Impl *implementation = 0;
+ ACE_NEW_RETURN (implementation,
+ ACE_WIN32_Asynch_Timer (handler,
+ act,
+ tv,
+ event,
+ priority,
+ signal_number),
+ 0);
+ return implementation;
+}
+
+int
+ACE_WIN32_Proactor::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ // Perform a non-blocking "poll" for all the I/O events that have
+ // completed in the I/O completion queue.
+
+ int result = 0;
+
+ for (ACE_Time_Value timeout (0, 0);
+ ;
+ )
+ {
+ result = this->handle_events (timeout);
+
+ if (result != 0 || errno == ETIME)
+ break;
+ }
+
+ // If our handle_events failed, we'll report a failure to the
+ // Reactor.
+ return result == -1 ? -1 : 0;
+}
+
+int
+ACE_WIN32_Proactor::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask)
+{
+ ACE_UNUSED_ARG (close_mask);
+ ACE_UNUSED_ARG (handle);
+
+ return this->close ();
+}
+
+ACE_HANDLE
+ACE_WIN32_Proactor::get_handle (void) const
+{
+ if (this->used_with_reactor_event_loop_)
+ return this->event_.handle ();
+ else
+ return 0;
+}
+
+int
+ACE_WIN32_Proactor::handle_events (ACE_Time_Value &wait_time)
+{
+ // Decrement <wait_time> with the amount of time spent in the method
+ ACE_Countdown_Time countdown (&wait_time);
+ return this->handle_events (wait_time.msec ());
+}
+
+int
+ACE_WIN32_Proactor::handle_events (void)
+{
+ return this->handle_events (ACE_INFINITE);
+}
+
+int
+ACE_WIN32_Proactor::handle_events (unsigned long milli_seconds)
+{
+ ACE_OVERLAPPED *overlapped = 0;
+ u_long bytes_transferred = 0;
+ u_long completion_key = 0;
+
+ // Get the next asynchronous operation that completes
+ BOOL result = ::GetQueuedCompletionStatus (this->completion_port_,
+ &bytes_transferred,
+ &completion_key,
+ &overlapped,
+ milli_seconds);
+ if (result == FALSE && overlapped == 0)
+ {
+ ACE_OS::set_errno_to_last_error ();
+
+ if (errno == WAIT_TIMEOUT)
+ {
+ errno = ETIME;
+ return 0;
+ }
+ else
+ {
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("GetQueuedCompletionStatus")));
+ }
+ return -1;
+ }
+ }
+ else
+ {
+ // Narrow the result.
+ ACE_WIN32_Asynch_Result *asynch_result = (ACE_WIN32_Asynch_Result *) overlapped;
+
+ // If errors happen, grab the error.
+ if (result == FALSE)
+ ACE_OS::set_errno_to_last_error ();
+ else
+ errno = 0;
+
+ u_long result_err = asynch_result->error ();
+
+ // if "result_err" is 0 than
+ // It is normal OS/WIN32 AIO completion.
+ // We have cleared asynch_result->error_
+ // during shared_read/shared_write.
+ // The real error code is already stored in "errno",
+ // so copy "errno" value to the "result_err"
+ // and pass this "result_err" code
+ // to the application_specific_code ()
+ // else
+ // "result_err" non zero
+ // it means we have "post_completed" result
+ // so pass this "result_err" code
+ // to the application_specific_code ()
+
+ if ( result_err == 0 )
+ result_err = errno ;
+
+ this->application_specific_code (asynch_result,
+ bytes_transferred,
+ result,
+ (void *) completion_key,
+ result_err);
+ }
+ return 1;
+}
+
+void
+ACE_WIN32_Proactor::application_specific_code (ACE_WIN32_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ ACE_SEH_TRY
+ {
+ // Call completion hook
+ asynch_result->complete (bytes_transferred,
+ success,
+ (void *) completion_key,
+ error);
+ }
+ ACE_SEH_FINALLY
+ {
+ // This is crucial to prevent memory leaks
+ delete asynch_result;
+ }
+}
+
+int
+ACE_WIN32_Proactor::post_completion (ACE_WIN32_Asynch_Result *result)
+{
+ // Grab the event associated with the Proactor
+ HANDLE handle = this->get_handle ();
+
+ // If Proactor event is valid, signal it
+ if (handle != ACE_INVALID_HANDLE &&
+ handle != 0)
+ ACE_OS::event_signal (&handle);
+
+ // pass
+ // bytes_transferred
+ // completion_key
+ // to the ::PostQueuedCompletionStatus()
+ // error will be extracted later in handle_events()
+
+ u_long bytes_transferred = 0;
+ const void * completion_key = 0 ;
+
+ if ( result != 0 )
+ {
+ bytes_transferred = result->bytes_transferred ();
+ completion_key = result->completion_key();
+ }
+
+ // Post a completion
+ if (::PostQueuedCompletionStatus (this->completion_port_, // completion port
+ bytes_transferred, // number of bytes transferred
+ (ULONG) completion_key, // completion key
+ result // overlapped
+ ) == FALSE)
+ {
+ delete result;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("PostQueuedCompletionStatus failed")));
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WIN32_Proactor::post_wakeup_completions (int how_many)
+{
+ ACE_WIN32_Wakeup_Completion *wakeup_completion = 0;
+
+ for (ssize_t ci = 0; ci < how_many; ci++)
+ {
+ ACE_NEW_RETURN (wakeup_completion,
+ ACE_WIN32_Wakeup_Completion (this->wakeup_handler_),
+ -1);
+
+ if (wakeup_completion->post_completion (this) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_WIN32_Proactor::wake_up_dispatch_threads (void)
+{
+ return 0;
+}
+
+int
+ACE_WIN32_Proactor::close_dispatch_threads (int)
+{
+ return 0;
+}
+
+size_t
+ACE_WIN32_Proactor::number_of_threads (void) const
+{
+ return this->number_of_threads_;
+}
+
+void
+ACE_WIN32_Proactor::number_of_threads (size_t threads)
+{
+ this->number_of_threads_ = threads;
+}
+
+ACE_WIN32_Asynch_Timer::ACE_WIN32_Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority,
+ signal_number),
+ time_ (tv)
+{
+}
+
+void
+ACE_WIN32_Asynch_Timer::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ ACE_UNUSED_ARG (error);
+ ACE_UNUSED_ARG (completion_key);
+ ACE_UNUSED_ARG (success);
+ ACE_UNUSED_ARG (bytes_transferred);
+
+ this->handler_.handle_time_out (this->time_, this->act ());
+}
+
+ACE_WIN32_Wakeup_Completion::ACE_WIN32_Wakeup_Completion (ACE_Handler &handler,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number)
+ : ACE_Asynch_Result_Impl (),
+ ACE_WIN32_Asynch_Result (handler, act, event, 0, 0, priority, signal_number)
+{
+}
+
+ACE_WIN32_Wakeup_Completion::~ACE_WIN32_Wakeup_Completion (void)
+{
+}
+
+void
+ACE_WIN32_Wakeup_Completion::complete (u_long /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ this->handler_.handle_wakeup ();
+}
+
+#endif /* ACE_WIN32 */
diff --git a/ace/Demux/WIN32_Proactor.h b/ace/Demux/WIN32_Proactor.h
new file mode 100644
index 00000000000..409eded6307
--- /dev/null
+++ b/ace/Demux/WIN32_Proactor.h
@@ -0,0 +1,296 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file WIN32_Proactor.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali (irfan@cs.wustl.edu)
+ * @author Tim Harrison (harrison@cs.wustl.edu)
+ * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
+ * @author Roger Tragin <r.tragin@computer.org>
+ */
+//=============================================================================
+
+#ifndef ACE_WIN32_PROACTOR_H
+#define ACE_WIN32_PROACTOR_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+#include "ace/WIN32_Asynch_IO.h"
+#include "ace/Event_Handler.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+// WIN32 implementation of the Proactor.
+
+#include "ace/Proactor_Impl.h"
+
+// Forward declarations.
+class ACE_WIN32_Asynch_Result;
+class ACE_WIN32_Proactor_Timer_Handler;
+
+/**
+ * @class ACE_WIN32_Proactor
+ *
+ * @brief A manager for asynchronous event demultiplexing.
+ *
+ * See the Proactor pattern description at
+ * http://www.cs.wustl.edu/~schmidt/proactor.ps.gz for more
+ * details.
+ */
+class ACE_Export ACE_WIN32_Proactor : public ACE_Proactor_Impl
+{
+public:
+ /// A do nothing constructor.
+ ACE_WIN32_Proactor (size_t number_of_threads = 0,
+ int used_with_reactor_event_loop = 0);
+
+ /// Virtual destruction.
+ virtual ~ACE_WIN32_Proactor (void);
+
+ /// Close the IO completion port.
+ virtual int close (void);
+
+ /// This method adds the <handle> to the I/O completion port. This
+ /// function is a no-op function for Unix systems.
+ virtual int register_handle (ACE_HANDLE handle,
+ const void *completion_key);
+
+ /**
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (ACE_Time_Value &wait_time);
+
+ /**
+ * Block indefinitely until at least one event is dispatched.
+ * Dispatch a single set of events. If <wait_time> elapses before
+ * any events occur, return 0. Return 1 on success i.e., when a
+ * completion is dispatched, non-zero (-1) on errors and errno is
+ * set accordingly.
+ */
+ virtual int handle_events (void);
+
+ /**
+ * Post a result to the completion port of the Proactor. If errors
+ * occur, the result will be deleted by this method. If successful,
+ * the result will be deleted by the Proactor when the result is
+ * removed from the completion port. Therefore, the result should
+ * have been dynamically allocated and should be orphaned by the
+ * user once this method is called.
+ */
+ virtual int post_completion (ACE_WIN32_Asynch_Result *result);
+
+ /// Add wakeup dispatch threads (reinit).
+ int wake_up_dispatch_threads (void);
+
+ /// Close all dispatch threads.
+ int close_dispatch_threads (int wait);
+
+ /// Number of thread used as a parameter to CreatIoCompletionPort.
+ size_t number_of_threads (void) const;
+ void number_of_threads (size_t threads);
+
+ /// Get the event handle.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ virtual ACE_Asynch_Read_Stream_Impl *create_asynch_read_stream (void);
+ virtual ACE_Asynch_Write_Stream_Impl *create_asynch_write_stream (void);
+ virtual ACE_Asynch_Read_File_Impl *create_asynch_read_file (void);
+ virtual ACE_Asynch_Write_File_Impl *create_asynch_write_file (void);
+ virtual ACE_Asynch_Read_Dgram_Impl *create_asynch_read_dgram (void);
+ virtual ACE_Asynch_Write_Dgram_Impl *create_asynch_write_dgram (void);
+ virtual ACE_Asynch_Accept_Impl *create_asynch_accept (void);
+ virtual ACE_Asynch_Transmit_File_Impl *create_asynch_transmit_file (void);
+
+ // Methods used to create Asynch_IO_Result objects. We create the right
+ // objects here in these methods.
+
+ virtual ACE_Asynch_Read_Stream_Result_Impl *create_asynch_read_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Write_Stream_Result_Impl *create_asynch_write_stream_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Read_File_Result_Impl *create_asynch_read_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Write_File_Result_Impl *create_asynch_write_file_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_write,
+ const void* act,
+ u_long offset,
+ u_long offset_high,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ /// Create the correct implementation class for ACE_Asynch_Read_Dgram::Result.
+ virtual ACE_Asynch_Read_Dgram_Result_Impl *create_asynch_read_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_read,
+ int flags,
+ int protocol_family,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ /// Create the correct implementation class for ACE_Asynch_Write_Dgram::Result.
+ virtual ACE_Asynch_Write_Dgram_Result_Impl *create_asynch_write_dgram_result (ACE_Handler &handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block *message_block,
+ size_t bytes_to_write,
+ int flags,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Accept_Result_Impl *create_asynch_accept_result (ACE_Handler &handler,
+ ACE_HANDLE listen_handle,
+ ACE_HANDLE accept_handle,
+ ACE_Message_Block &message_block,
+ u_long bytes_to_read,
+ const void* act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ virtual ACE_Asynch_Transmit_File_Result_Impl *create_asynch_transmit_file_result (ACE_Handler &handler,
+ ACE_HANDLE socket,
+ ACE_HANDLE file,
+ ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
+ u_long bytes_to_write,
+ u_long offset,
+ u_long offset_high,
+ u_long bytes_per_send,
+ u_long flags,
+ const void *act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+ /// Create a timer result object which can be used with the Timer
+ /// mechanism of the Proactor.
+ virtual ACE_Asynch_Result_Impl *create_asynch_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number = 0);
+
+protected:
+ /// Called when object is signaled by OS (either via UNIX signals or
+ /// when a Win32 object becomes signaled).
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+
+ /// Called when object is removed from the ACE_Reactor.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ /**
+ * Dispatch a single set of events. If <milli_seconds> elapses
+ * before any events occur, return 0. Return 1 if a completion is
+ * dispatched. Return -1 on errors.
+ */
+ virtual int handle_events (unsigned long milli_seconds);
+
+ /// Protect against structured exceptions caused by user code when
+ /// dispatching handles.
+ void application_specific_code (ACE_WIN32_Asynch_Result *asynch_result,
+ u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error);
+
+ /**
+ * Post <how_many> completions to the completion port so that all
+ * threads can wake up. This is used in conjunction with the
+ * <run_event_loop>.
+ */
+ virtual int post_wakeup_completions (int how_many);
+
+ /// Handle for the completion port. Unix doesnt have completion
+ /// ports.
+ ACE_HANDLE completion_port_;
+
+ /// This number is passed to the <CreatIOCompletionPort> system
+ /// call.
+ size_t number_of_threads_;
+
+ /// This event is used in conjunction with Reactor when we try to
+ /// integrate the event loops of Reactor and the Proactor.
+ ACE_Auto_Event event_;
+
+ /// Flag that indicates whether we are used in conjunction with
+ /// Reactor.
+ int used_with_reactor_event_loop_;
+
+ /// Handler to handle the wakeups. This works in conjunction with the
+ /// <ACE_Proactor::run_event_loop>.
+ ACE_Handler wakeup_handler_;
+};
+
+/**
+ * @class ACE_WIN32_Asynch_Timer
+ *
+ * @brief This class is posted to the completion port when a timer
+ * expires. When the complete method of this object is
+ * called, the <handler>'s handle_timeout method will be
+ * called.
+ */
+class ACE_Export ACE_WIN32_Asynch_Timer : public ACE_WIN32_Asynch_Result
+{
+
+ /// The factory method for this class is with the POSIX_Proactor
+ /// class.
+ friend class ACE_WIN32_Proactor;
+
+protected:
+ /// Constructor.
+ ACE_WIN32_Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv,
+ ACE_HANDLE event = ACE_INVALID_HANDLE,
+ int priority = 0,
+ int signal_number = 0);
+
+ /// This method calls the <handler>'s handle_timeout method.
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0);
+
+ /// Time value requested by caller
+ ACE_Time_Value time_;
+};
+
+#endif /* ACE_WIN32 */
+#include "ace/post.h"
+#endif /* ACE_PROACTOR_H */
diff --git a/ace/IPC/Addr.cpp b/ace/IPC/Addr.cpp
new file mode 100644
index 00000000000..6b7c13d1442
--- /dev/null
+++ b/ace/IPC/Addr.cpp
@@ -0,0 +1,65 @@
+// Addr.cpp
+// $Id$
+
+#include "ace/IPC/Addr.h"
+#include "ace/Logging/Log_Msg.h"
+
+ACE_RCSID(ace, Addr, "$Id$")
+
+#if defined (ACE_HAS_BROKEN_SAP_ANY)
+#if defined (sap_any)
+#undef sap_any
+// Note: this object requires static construction and destruction.
+/* static */
+const ACE_Addr ace_sap_any (AF_ANY, -1);
+
+const ACE_Addr &
+ACE_Addr::sap_any (void)
+{
+ return ace_sap_any;
+}
+#define sap_any sap_any()
+#endif /* sap_any */
+#else
+// Note: this object requires static construction and destruction.
+/* static */
+const ACE_Addr ACE_Addr::sap_any (AF_ANY, -1);
+#endif /* ACE_HAS_BROKEN_SAP_ANY */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IPC/Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Addr)
+
+void
+ACE_Addr::dump (void) const
+{
+ ACE_TRACE ("ACE_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("addr_type_ = %d"), this->addr_type_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\naddr_size_ = %d"), this->addr_size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Initializes instance variables.
+
+void
+ACE_Addr::base_set (int type, int size)
+{
+ this->addr_type_ = type;
+ this->addr_size_ = size;
+}
+
+// Initializes instance variables. Note that 0 is an unspecified
+// protocol family type...
+
+ACE_Addr::ACE_Addr (int type, int size)
+{
+ this->base_set (type, size);
+}
+
+ACE_Addr::~ACE_Addr (void)
+{
+}
diff --git a/ace/IPC/Addr.h b/ace/IPC/Addr.h
new file mode 100644
index 00000000000..8a9de5ba0f9
--- /dev/null
+++ b/ace/IPC/Addr.h
@@ -0,0 +1,106 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Addr.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_ADDR_H
+#define ACE_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/OS/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Addr
+ *
+ * @brief Defines the base class for the "address family independent"
+ * address format.
+ */
+class ACE_Export ACE_Addr
+{
+public:
+ // = Initialization and termination methods.
+ /// Initializes instance variables.
+ ACE_Addr (int type = -1,
+ int size = -1);
+
+ /// Destructor.
+ virtual ~ACE_Addr (void);
+
+ // = Get/set the size of the address.
+
+ /// Return the size of the address.
+ int get_size (void) const;
+
+ /// Sets the size of the address.
+ void set_size (int size);
+
+ // = Get/set the type of the address.
+
+ /// Get the type of the address.
+ int get_type (void) const;
+
+ /// Set the type of the address.
+ void set_type (int type);
+
+ /// Return a pointer to the address.
+ virtual void *get_addr (void) const;
+
+ /// Set a pointer to the address.
+ virtual void set_addr (void *, int len);
+
+ // = Equality/inequality tests
+ /// Check for address equality.
+ int operator == (const ACE_Addr &sap) const;
+
+ /// Check for address inequality.
+ int operator != (const ACE_Addr &sap) const;
+
+ /// Initializes instance variables.
+ void base_set (int type, int size);
+
+#if defined (ACE_HAS_BROKEN_SAP_ANY)
+ /// Wild-card address.
+ static const ACE_Addr &sap_any (void);
+
+ // This #define works around broken C++ compilers...
+#define sap_any sap_any()
+#else
+ /// Wild-card address.
+ static const ACE_Addr sap_any;
+#endif /* ACE_HAS_BROKEN_SAP_ANY */
+
+ /// Returns a hash value. This should be overwritten by a subclass
+ /// that can produce a better hash value.
+ virtual u_long hash (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// e.g., AF_UNIX, AF_INET, AF_SPIPE, etc.
+ int addr_type_;
+
+ /// Number of bytes in the address.
+ int addr_size_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/IPC/Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_ADDR_H */
diff --git a/ace/IPC/Addr.i b/ace/IPC/Addr.i
new file mode 100644
index 00000000000..db4f4e605c8
--- /dev/null
+++ b/ace/IPC/Addr.i
@@ -0,0 +1,69 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Addr.i
+
+// Return the address of the address.
+
+ACE_INLINE void *
+ACE_Addr::get_addr (void) const
+{
+ return 0;
+}
+
+ACE_INLINE void
+ACE_Addr::set_addr (void *, int)
+{
+}
+
+ACE_INLINE int
+ACE_Addr::operator == (const ACE_Addr &sap) const
+{
+ return (sap.addr_type_ == this->addr_type_ &&
+ sap.addr_size_ == this->addr_size_ );
+}
+
+ACE_INLINE int
+ACE_Addr::operator != (const ACE_Addr &sap) const
+{
+ return (sap.addr_type_ != this->addr_type_ ||
+ sap.addr_size_ != this->addr_size_ );
+}
+
+// Return the size of the address.
+
+ACE_INLINE int
+ACE_Addr::get_size (void) const
+{
+ return this->addr_size_;
+}
+
+// Sets the size of the address.
+
+ACE_INLINE void
+ACE_Addr::set_size (int size)
+{
+ this->addr_size_ = size;
+}
+
+// Return the type of the address.
+
+ACE_INLINE int
+ACE_Addr::get_type (void) const
+{
+ return this->addr_type_;
+}
+
+// Set the type of the address.
+
+ACE_INLINE void
+ACE_Addr::set_type (int type)
+{
+ this->addr_type_ = type;
+}
+
+ACE_INLINE u_long
+ACE_Addr::hash (void) const
+{
+ return 0;
+}
diff --git a/ace/IPC/DEV.cpp b/ace/IPC/DEV.cpp
new file mode 100644
index 00000000000..0aa66003edb
--- /dev/null
+++ b/ace/IPC/DEV.cpp
@@ -0,0 +1,37 @@
+// DEV.cpp
+// $Id$
+
+
+#include "ace/DEV.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV.i"
+#endif
+
+ACE_RCSID(ace, DEV, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV)
+
+void
+ACE_DEV::dump (void) const
+{
+ ACE_TRACE ("ACE_DEV::dump");
+}
+
+// This is the do-nothing constructor.
+
+ACE_DEV::ACE_DEV (void)
+{
+ ACE_TRACE ("ACE_DEV::ACE_DEV");
+}
+
+// Close the device
+
+int
+ACE_DEV::close (void)
+{
+ ACE_TRACE ("ACE_DEV::close");
+ int result = ACE_OS::close (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ return result;
+}
diff --git a/ace/IPC/DEV.h b/ace/IPC/DEV.h
new file mode 100644
index 00000000000..46213ececdf
--- /dev/null
+++ b/ace/IPC/DEV.h
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file DEV.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ */
+//=============================================================================
+
+
+#ifndef ACE_DEV_H
+#define ACE_DEV_H
+#include "ace/pre.h"
+
+#include "ace/IO_SAP.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/DEV_Addr.h"
+
+// The following is necessary since many C++ compilers don't support
+// typedef'd types inside of classes used as formal template
+// arguments... ;-(. Luckily, using the C++ preprocessor I can hide
+// most of this nastiness!
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+#define ACE_DEV_CONNECTOR ACE_DEV_Connector
+#define ACE_DEV_STREAM ACE_DEV_Stream
+#else /* TEMPLATES are broken (must be a cfront-based compiler...) */
+#define ACE_DEV_CONNECTOR ACE_DEV_Connector, ACE_DEV_Addr
+#define ACE_DEV_STREAM ACE_DEV_Stream, ACE_DEV_Addr
+#endif /* ACE_TEMPLATE_TYPEDEFS */
+
+/**
+ * @class ACE_DEV
+ *
+ * @brief Defines the member functions for the base class of the
+ * ACE_DEV abstraction.
+ */
+class ACE_Export ACE_DEV : public ACE_IO_SAP
+{
+public:
+ /// Close down the DEVICE
+ int close (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /**
+ * Disable signal <signum>
+ * This is here to prevent Win32 from
+ * disabling SPIPE using socket calls
+ */
+ int disable (int signum) const ;
+
+protected:
+ /// Ensure that this class is an abstract base class
+ ACE_DEV (void);
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_DEV_H */
diff --git a/ace/IPC/DEV.i b/ace/IPC/DEV.i
new file mode 100644
index 00000000000..529824f129c
--- /dev/null
+++ b/ace/IPC/DEV.i
@@ -0,0 +1,15 @@
+/* -*- C++ -*- */
+// $Id$
+
+// DEV.i
+
+ASYS_INLINE int
+ACE_DEV::disable (int signum) const
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (signum) ;
+ return 0 ;
+#else /* ACE_WIN32 */
+ return ACE_IO_SAP::disable (signum) ;
+#endif /* ACE_WIN32 */
+}
diff --git a/ace/IPC/DEV_Addr.cpp b/ace/IPC/DEV_Addr.cpp
new file mode 100644
index 00000000000..43dde161857
--- /dev/null
+++ b/ace/IPC/DEV_Addr.cpp
@@ -0,0 +1,81 @@
+// DEV_Addr.cpp
+// $Id$
+
+#include "ace/DEV_Addr.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/DEV_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, DEV_Addr, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Addr)
+
+void
+ACE_DEV_Addr::dump (void) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("devname_ = %s"), this->devname_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Do nothing constructor.
+
+ACE_DEV_Addr::ACE_DEV_Addr (void)
+ : ACE_Addr (AF_DEV, sizeof this->devname_)
+{
+ ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr");
+
+ (void) ACE_OS::memset ((void *) &this->devname_,
+ 0, sizeof this->devname_);
+}
+
+int
+ACE_DEV_Addr::set (const ACE_DEV_Addr &sa)
+{
+ this->base_set (sa.get_type (), sa.get_size ());
+
+ if (sa.get_type () == AF_ANY)
+ (void) ACE_OS::memset ((void *) &this->devname_,
+ 0,
+ sizeof this->devname_);
+ else
+ (void) ACE_OS::memcpy ((void *) &this->devname_,
+ (void *) &sa.devname_,
+ sa.get_size ());
+ return 0;
+}
+
+// Copy constructor.
+
+ACE_DEV_Addr::ACE_DEV_Addr (const ACE_DEV_Addr &sa)
+ : ACE_Addr (AF_DEV, sizeof this->devname_)
+{
+ ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr");
+
+ this->set (sa);
+}
+
+ACE_DEV_Addr::ACE_DEV_Addr (const ACE_TCHAR *devname)
+ : ACE_Addr (AF_DEV, sizeof this->devname_)
+{
+ ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr");
+
+ this->set (devname);
+}
+
+ACE_DEV_Addr &
+ACE_DEV_Addr::operator= (const ACE_DEV_Addr &sa)
+{
+ ACE_TRACE ("ACE_DEV_Addr::operator=");
+
+ if (this != &sa)
+ (void) ACE_OS::memcpy ((void *) &this->devname_,
+ (void *) &sa.devname_,
+ sa.get_size ());
+ return *this;
+}
+
diff --git a/ace/IPC/DEV_Addr.h b/ace/IPC/DEV_Addr.h
new file mode 100644
index 00000000000..a270004ea31
--- /dev/null
+++ b/ace/IPC/DEV_Addr.h
@@ -0,0 +1,84 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file DEV_Addr.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer and Douglas C. Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_DEV_ADDR_H
+#define ACE_DEV_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+
+/**
+ * @class ACE_DEV_Addr
+ *
+ * @brief Defines device address family address format.
+ */
+class ACE_Export ACE_DEV_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_DEV_Addr (void);
+
+ /// Copy constructor.
+ ACE_DEV_Addr (const ACE_DEV_Addr &sa);
+
+ /// Acts like a copy constructor.
+ int set (const ACE_DEV_Addr &sa);
+
+ /// Create a ACE_DEV_Addr from a device name.
+ ACE_EXPLICIT ACE_DEV_Addr (const ACE_TCHAR *devname);
+
+ /// Create a ACE_Addr from a ACE_DEV pathname.
+ void set (const ACE_TCHAR *devname);
+
+ /// Assignment operator.
+ ACE_DEV_Addr &operator= (const ACE_DEV_Addr &);
+
+ /// Return a pointer to the address.
+ virtual void *get_addr (void) const;
+
+ /// Transform the current address into string format.
+ virtual int addr_to_string (ACE_TCHAR *addr, size_t) const;
+
+ /// Compare two addresses for equality.
+ int operator == (const ACE_DEV_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ int operator != (const ACE_DEV_Addr &SAP) const;
+
+ /// Return the path name used for the rendezvous point.
+ const ACE_TCHAR *get_path_name (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Name of the device.
+ ACE_TCHAR devname_[MAXNAMLEN + 1];
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/DEV_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_DEV_ADDR_H */
diff --git a/ace/IPC/DEV_Addr.i b/ace/IPC/DEV_Addr.i
new file mode 100644
index 00000000000..53ff88d47bc
--- /dev/null
+++ b/ace/IPC/DEV_Addr.i
@@ -0,0 +1,64 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/SString.h"
+
+ACE_INLINE void
+ACE_DEV_Addr::set (const ACE_TCHAR *devname)
+{
+ ACE_TRACE ("ACE_DEV_Addr::set");
+
+ this->ACE_Addr::base_set (AF_DEV, ACE_OS::strlen (devname));
+ ACE_OS::strsncpy (this->devname_, devname, MAXNAMLEN);
+}
+
+// Transform the current address into string format.
+
+ACE_INLINE int
+ACE_DEV_Addr::addr_to_string (ACE_TCHAR *s, size_t len) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::addr_to_string");
+
+ ACE_OS::strsncpy (s, this->devname_, len);
+ return 0;
+}
+
+// Return a pointer to the address.
+
+ACE_INLINE void *
+ACE_DEV_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::get_addr");
+
+ return (void *) &this->devname_;
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE int
+ACE_DEV_Addr::operator == (const ACE_DEV_Addr &sap) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::operator ==");
+
+ return ACE_OS::strcmp (this->devname_, sap.devname_) == 0;
+}
+
+// Compare two addresses for inequality.
+
+ACE_INLINE int
+ACE_DEV_Addr::operator != (const ACE_DEV_Addr &sap) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::operator !=");
+
+ return !((*this) == sap); // This is lazy, of course... ;-).
+}
+
+// Return the path name used for the rendezvous point.
+
+ACE_INLINE const ACE_TCHAR *
+ACE_DEV_Addr::get_path_name (void) const
+{
+ ACE_TRACE ("ACE_DEV_Addr::get_path_name");
+
+ return this->devname_;
+}
diff --git a/ace/IPC/DEV_Connector.cpp b/ace/IPC/DEV_Connector.cpp
new file mode 100644
index 00000000000..35463c05aaf
--- /dev/null
+++ b/ace/IPC/DEV_Connector.cpp
@@ -0,0 +1,43 @@
+// DEV_Connector.cpp
+// $Id$
+
+#include "ace/DEV_Connector.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV_Connector.i"
+#endif
+
+ACE_RCSID(ace, DEV_Connector, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Connector)
+
+void
+ACE_DEV_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_DEV_Connector::dump");
+}
+
+ACE_DEV_Connector::ACE_DEV_Connector (void)
+{
+ ACE_TRACE ("ACE_DEV_Connector::ACE_DEV_Connector");
+}
+
+int
+ACE_DEV_Connector::connect (ACE_DEV_IO &new_io,
+ const ACE_DEV_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &,
+ int,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_DEV_Connector::connect");
+
+ ACE_HANDLE handle = ACE_Handle_Ops::handle_timed_open (timeout,
+ remote_sap.get_path_name (),
+ flags, perms);
+ new_io.set_handle (handle);
+ new_io.addr_ = remote_sap; // class copy.
+ return handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
diff --git a/ace/IPC/DEV_Connector.h b/ace/IPC/DEV_Connector.h
new file mode 100644
index 00000000000..c43e726cd59
--- /dev/null
+++ b/ace/IPC/DEV_Connector.h
@@ -0,0 +1,104 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file DEV_Connector.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer and Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_DEV_CONNECTOR_H
+#define ACE_DEV_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/DEV_IO.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_DEV_Connector
+ *
+ * @brief Defines an active connection factory for the ACE_DEV wrappers.
+ */
+class ACE_Export ACE_DEV_Connector
+{
+public:
+ /// Default constructor.
+ ACE_DEV_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ ACE_DEV_Connector (ACE_DEV_IO &new_io,
+ const ACE_DEV_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ int connect (ACE_DEV_IO &new_io,
+ const ACE_DEV_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Meta-type info
+ typedef ACE_DEV_Addr PEER_ADDR;
+ typedef ACE_DEV_IO PEER_STREAM;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV_Connector.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_DEV_CONNECTOR_H */
diff --git a/ace/IPC/DEV_Connector.i b/ace/IPC/DEV_Connector.i
new file mode 100644
index 00000000000..8b2af2372f0
--- /dev/null
+++ b/ace/IPC/DEV_Connector.i
@@ -0,0 +1,30 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Creates a Local ACE_DEV.
+
+ASYS_INLINE
+ACE_DEV_Connector::ACE_DEV_Connector (ACE_DEV_IO &new_io,
+ const ACE_DEV_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_DEV_Connector::ACE_DEV_Connector");
+ if (this->connect (new_io, remote_sap, timeout, local_sap,
+ reuse_addr, flags, perms) == ACE_IO_SAP::INVALID_HANDLE
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (), ACE_LIB_TEXT ("ACE_DEV_IO")));
+}
+
+ASYS_INLINE int
+ACE_DEV_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_UNUSED_ARG (handle);
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
+
diff --git a/ace/IPC/DEV_IO.cpp b/ace/IPC/DEV_IO.cpp
new file mode 100644
index 00000000000..a6dbee87627
--- /dev/null
+++ b/ace/IPC/DEV_IO.cpp
@@ -0,0 +1,126 @@
+// DEV_IO.cpp
+// $Id$
+
+#include "ace/DEV_IO.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV_IO.i"
+#endif
+
+ACE_RCSID(ace, DEV_IO, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_DEV_IO)
+
+// Return the local endpoint address.
+
+int
+ACE_DEV_IO::get_local_addr (ACE_DEV_Addr &addr) const
+{
+ ACE_TRACE ("ACE_DEV_IO::get_local_addr");
+
+ addr = this->addr_;
+ return 0;
+}
+
+// Return the address of the remotely connected peer (if there is
+// one).
+
+int
+ACE_DEV_IO::get_remote_addr (ACE_DEV_Addr &addr) const
+{
+ ACE_TRACE ("ACE_DEV_IO::get_remote_addr");
+ addr = this->addr_;
+ return 0;
+}
+
+void
+ACE_DEV_IO::dump (void) const
+{
+ ACE_TRACE ("ACE_DEV_IO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Simple-minded do nothing constructor.
+
+ACE_DEV_IO::ACE_DEV_IO (void)
+{
+ ACE_TRACE ("ACE_DEV_IO::ACE_DEV_IO");
+}
+
+// Send N char *ptrs and int lengths. Note that the char *'s precede
+// the ints (basically, an varargs version of writev). The count N is
+// the *total* number of trailing arguments, *not* a couple of the
+// number of tuple pairs!
+
+ssize_t
+ACE_DEV_IO::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::writev (this->get_handle (), iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// This is basically an interface to ACE_OS::readv, that doesn't use the
+// struct iovec explicitly. The ... can be passed as an arbitrary
+// number of (char *ptr, int len) tuples. However, the count N is the
+// *total* number of trailing arguments, *not* a couple of the number
+// of tuple pairs!
+
+ssize_t
+ACE_DEV_IO::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::readv (this->get_handle (), iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
diff --git a/ace/IPC/DEV_IO.h b/ace/IPC/DEV_IO.h
new file mode 100644
index 00000000000..3e5ed037bbf
--- /dev/null
+++ b/ace/IPC/DEV_IO.h
@@ -0,0 +1,134 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file DEV_IO.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ @ @author Douglas C. Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_DEV_IO_H
+#define ACE_DEV_IO_H
+#include "ace/pre.h"
+
+#include "ace/DEV.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/DEV_Addr.h"
+
+/**
+ * @class ACE_DEV_IO
+ *
+ * @brief Read/Write operations on Devices.
+ */
+class ACE_Export ACE_DEV_IO : public ACE_DEV
+{
+public:
+ friend class ACE_DEV_Connector;
+
+ /// Default constructor.
+ ACE_DEV_IO (void);
+
+ // = Various send operations.
+ /// send upto <n> bytes in <buf>.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv upto <n> bytes in <buf>.
+ ssize_t recv (void *buf, size_t n) const;
+
+ /// Send n bytes, keep trying until n are sent.
+ ssize_t send_n (const void *buf, size_t n) const;
+
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t recv_n (void *buf, size_t n) const;
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Recv bytes via STREAM pipes using "band" mode.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *band,
+ int *flags) const;
+
+ /// Send bytes via STREAM pipes using "band" mode.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int band,
+ int flags) const;
+
+ /// Recv <cntl> and <data> via STREAM pipes.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *flags) const;
+
+ /// Send <cntl> and <data> via STREAM pipes.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int flags = 0) const;
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ /// Send iovecs via <::writev>.
+ ssize_t send (const iovec iov[], size_t n) const;
+
+ /// Recv iovecs via <::readv>.
+ ssize_t recv (iovec iov[], size_t n) const;
+
+ /**
+ * Send N char *ptrs and int lengths. Note that the char *'s
+ * precede the ints (basically, an varargs version of writev). The
+ * count N is the *total* number of trailing arguments, *not* a
+ * couple of the number of tuple pairs!
+ */
+ ssize_t send (size_t n, ...) const;
+
+ /**
+ * This is an interface to ::readv, that doesn't use the struct
+ * iovec explicitly. The ... can be passed as an arbitrary number
+ * of (char *ptr, int len) tuples. However, the count N is the
+ * *total* number of trailing arguments, *not* a couple of the
+ * number of tuple pairs!
+ */
+ ssize_t recv (size_t n, ...) const;
+
+ /// Send <n> bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv <n> bytes via Win32 ReadFile using overlapped I/O.
+ ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ // = The following two methods are no-ops to keep the
+ // <ACE_Connector> happy.
+ /// Return the local endpoint address.
+ int get_local_addr (ACE_DEV_Addr &) const;
+
+ /// Return the address of the remotely connected peer (if there is
+ /// one).
+ int get_remote_addr (ACE_DEV_Addr &) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Meta-type info
+ typedef ACE_DEV_Addr PEER_ADDR;
+
+private:
+ /// Address of device we are connected to.
+ ACE_DEV_Addr addr_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/DEV_IO.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_DEV_IO_H */
diff --git a/ace/IPC/DEV_IO.i b/ace/IPC/DEV_IO.i
new file mode 100644
index 00000000000..90c825ebf50
--- /dev/null
+++ b/ace/IPC/DEV_IO.i
@@ -0,0 +1,101 @@
+/* -*- C++ -*- */
+// $Id$
+
+// DEV_IO.i
+
+// Send exactly N bytes from BUF to this device. Keeping trying until
+// this many bytes are sent.
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send_n (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send_n");
+ return ACE::write_n (this->get_handle (), buf, n);
+}
+
+// Receive exactly N bytes from this file into BUF. Keep trying until
+// this many bytes are received.
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv_n (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv_n");
+ return ACE::read_n (this->get_handle (), buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ return ACE_OS::write (this->get_handle (), (const char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send (const iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv (iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ return ACE_OS::readv (this->get_handle (), iov, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send (const void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ return ACE_OS::write (this->get_handle (),
+ (const char *) buf, n,
+ overlapped);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv (void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, n,
+ overlapped);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const
+{
+ ACE_TRACE ("ACE_DEV_IO::recv");
+ return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_DEV_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const
+{
+ ACE_TRACE ("ACE_DEV_IO::send");
+ return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ace/IPC/FIFO.cpp b/ace/IPC/FIFO.cpp
new file mode 100644
index 00000000000..99016a7e93d
--- /dev/null
+++ b/ace/IPC/FIFO.cpp
@@ -0,0 +1,74 @@
+// FIFO.cpp
+// $Id$
+
+#include "ace/FIFO.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FIFO.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FIFO, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO)
+
+void
+ACE_FIFO::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("rendezvous_ = %s"), this->rendezvous_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_FIFO::open (const ACE_TCHAR *r, int flags, int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO::open");
+ ACE_OS::strsncpy (this->rendezvous_, r, MAXPATHLEN);
+
+#if defined (ACE_PSOS_DIAB_MIPS)
+ if ( ACE_OS::mkfifo (this->rendezvous_, perms) == -1
+ && !(errno == EEXIST))
+ return -1;
+#else
+ if ((flags & O_CREAT) != 0
+ && ACE_OS::mkfifo (this->rendezvous_, perms) == -1
+ && !(errno == EEXIST))
+ return -1;
+#endif
+
+ this->set_handle (ACE_OS::open (this->rendezvous_, flags, 0, sa));
+ return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+ACE_FIFO::ACE_FIFO (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO::ACE_FIFO");
+ if (this->open (fifo_name, flags, perms, sa) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_FIFO")));
+}
+
+ACE_FIFO::ACE_FIFO (void)
+{
+// ACE_TRACE ("ACE_FIFO::ACE_FIFO");
+}
+
+int
+ACE_FIFO::close (void)
+{
+ ACE_TRACE ("ACE_FIFO::close");
+ int result = 0;
+
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ result = ACE_OS::close (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ }
+ return result;
+}
diff --git a/ace/IPC/FIFO.h b/ace/IPC/FIFO.h
new file mode 100644
index 00000000000..bd8ea10d2f2
--- /dev/null
+++ b/ace/IPC/FIFO.h
@@ -0,0 +1,79 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FIFO.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_FIFO_H
+#define ACE_FIFO_H
+#include "ace/pre.h"
+
+#include "ace/IPC_SAP.h"
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FIFO
+ *
+ * @brief Abstract base class for UNIX FIFOs
+ *
+ * UNIX FIFOs are also known Named Pipes, which are totally
+ * unrelated to Win32 Named Pipes. If you want to use a local
+ * IPC mechanism that will be portable to both UNIX and Win32,
+ * take a look at the <ACE_SPIPE_*> classes.
+ */
+class ACE_Export ACE_FIFO : public ACE_IPC_SAP
+{
+public:
+ /// Open up the named pipe on the <rendezvous> in accordance with the
+ /// flags.
+ int open (const ACE_TCHAR *rendezvous, int flags, int perms,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Close down the ACE_FIFO without removing the rendezvous point.
+ int close (void);
+
+ /// Close down the ACE_FIFO and remove the rendezvous point from the
+ /// file system.
+ int remove (void);
+
+ /// Return the local address of this endpoint.
+ int get_local_addr (const ACE_TCHAR *&rendezvous) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Make these protected to ensure that the class is "abstract."
+ /// Default constructor.
+ ACE_FIFO (void);
+
+ /// Open up the named pipe on the <rendezvous> in accordance with the
+ /// flags.
+ ACE_FIFO (const ACE_TCHAR *rendezvous, int flags, int perms,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+private:
+ /// Rendezvous point in the file system.
+ ACE_TCHAR rendezvous_[MAXPATHLEN + 1];
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/FIFO.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_FIFO_H */
diff --git a/ace/IPC/FIFO.i b/ace/IPC/FIFO.i
new file mode 100644
index 00000000000..d640bb8141f
--- /dev/null
+++ b/ace/IPC/FIFO.i
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FIFO.i
+
+ACE_INLINE int
+ACE_FIFO::get_local_addr (const ACE_TCHAR *&r) const
+{
+ ACE_TRACE ("ACE_FIFO::get_local_addr");
+ r = this->rendezvous_;
+ return 0;
+}
+
+ACE_INLINE int
+ACE_FIFO::remove (void)
+{
+ ACE_TRACE ("ACE_FIFO::remove");
+ int result = this->close ();
+ return ACE_OS::unlink (this->rendezvous_) == -1 || result == -1 ? -1 : 0;
+}
diff --git a/ace/IPC/FIFO_Recv.cpp b/ace/IPC/FIFO_Recv.cpp
new file mode 100644
index 00000000000..7b10a89e017
--- /dev/null
+++ b/ace/IPC/FIFO_Recv.cpp
@@ -0,0 +1,82 @@
+// FIFO_Recv.cpp
+// $Id$
+
+#include "ace/FIFO_Recv.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Recv.i"
+#endif
+
+ACE_RCSID(ace, FIFO_Recv, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv)
+
+void
+ACE_FIFO_Recv::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO_Recv::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_FIFO::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("aux_handle_ = %d"), this->aux_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_FIFO_Recv::close (void)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::close");
+ int result = ACE_FIFO::close ();
+
+ if (this->aux_handle_ != ACE_INVALID_HANDLE)
+ return ACE_OS::close (this->aux_handle_);
+ else
+ return result;
+}
+
+// Note that persistent means "open fifo for writing, as well as
+// reading." This ensures that the fifo never gets EOF, even if there
+// aren't any writers at the moment!
+
+int
+ACE_FIFO_Recv::open (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ int persistent,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::open");
+
+ if (ACE_FIFO::open (fifo_name, ACE_NONBLOCK | flags, perms, sa) == -1)
+ return -1;
+ else if (this->disable (ACE_NONBLOCK) == -1)
+ return -1;
+ else if (persistent
+ && (this->aux_handle_ = ACE_OS::open (fifo_name, O_WRONLY, 0, sa)) == ACE_INVALID_HANDLE)
+ return -1;
+ else
+ return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+ACE_FIFO_Recv::ACE_FIFO_Recv (void)
+ : aux_handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::ACE_FIFO_Recv");
+}
+
+ACE_FIFO_Recv::ACE_FIFO_Recv (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ int persistent,
+ LPSECURITY_ATTRIBUTES sa)
+ : aux_handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::ACE_FIFO_Recv");
+
+ if (this->ACE_FIFO_Recv::open (fifo_name,
+ flags,
+ perms,
+ persistent,
+ sa) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_FIFO_Recv")));
+}
diff --git a/ace/IPC/FIFO_Recv.h b/ace/IPC/FIFO_Recv.h
new file mode 100644
index 00000000000..6767cf4ab7b
--- /dev/null
+++ b/ace/IPC/FIFO_Recv.h
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FIFO_Recv.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_FIFO_RECV_H
+#define ACE_FIFO_RECV_H
+#include "ace/pre.h"
+
+#include "ace/FIFO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FIFO_Recv
+ *
+ * @brief Receiver side of the bytestream C++ wrapper for UNIX
+ * FIFOs.
+ */
+class ACE_Export ACE_FIFO_Recv : public ACE_FIFO
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FIFO_Recv (void);
+
+ /// Open up a bytestream named pipe for reading.
+ ACE_FIFO_Recv (const ACE_TCHAR *rendezvous,
+ int flags = O_CREAT | O_RDONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Open up a bytestream named pipe for reading.
+ int open (const ACE_TCHAR *rendezvous,
+ int flags = O_CREAT | O_RDONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Close down the named pipe.
+ int close (void);
+
+ /// Recv <buf> of up to <len> bytes.
+ ssize_t recv (void *buf, size_t len);
+
+ /// Recv <buf> of exactly <len> bytes (block until done).
+ ssize_t recv_n (void *buf, size_t len);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Auxiliary handle that is used to implement persistent FIFOs.
+ ACE_HANDLE aux_handle_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Recv.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_FIFO_RECV_H */
diff --git a/ace/IPC/FIFO_Recv.i b/ace/IPC/FIFO_Recv.i
new file mode 100644
index 00000000000..693b2a944fe
--- /dev/null
+++ b/ace/IPC/FIFO_Recv.i
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FIFO_Recv.i
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv::recv (void *buf, size_t len)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, len);
+}
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv::recv_n (void *buf, size_t n)
+{
+ ACE_TRACE ("ACE_FIFO_Recv::recv_n");
+ return ACE::recv_n (this->get_handle (), buf, n);
+}
diff --git a/ace/IPC/FIFO_Recv_Msg.cpp b/ace/IPC/FIFO_Recv_Msg.cpp
new file mode 100644
index 00000000000..714cc43986f
--- /dev/null
+++ b/ace/IPC/FIFO_Recv_Msg.cpp
@@ -0,0 +1,61 @@
+// FIFO_Recv_Msg.cpp
+// $Id$
+
+#include "ace/FIFO_Recv_Msg.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Recv_Msg.i"
+#endif
+
+ACE_RCSID(ace, FIFO_Recv_Msg, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv_Msg)
+
+void
+ACE_FIFO_Recv_Msg::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::dump");
+ ACE_FIFO_Recv::dump ();
+}
+
+// Note that persistent means "open FIFO for writing, as well as
+// reading." This ensures that the FIFO never gets EOF, even if there
+// aren't any writers at the moment!
+
+int
+ACE_FIFO_Recv_Msg::open (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ int persistent,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::open");
+
+ return ACE_FIFO_Recv::open (fifo_name,
+ flags,
+ perms,
+ persistent,
+ sa);
+}
+
+ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg (void)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg");
+}
+
+ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ int persistent,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg");
+
+ if (this->ACE_FIFO_Recv_Msg::open (fifo_name,
+ flags,
+ perms,
+ persistent,
+ sa) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_FIFO_Recv_Msg")));
+}
diff --git a/ace/IPC/FIFO_Recv_Msg.h b/ace/IPC/FIFO_Recv_Msg.h
new file mode 100644
index 00000000000..3920e063630
--- /dev/null
+++ b/ace/IPC/FIFO_Recv_Msg.h
@@ -0,0 +1,81 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FIFO_Recv_Msg.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_FIFO_RECV_MSG_H
+#define ACE_FIFO_RECV_MSG_H
+#include "ace/pre.h"
+
+#include "ace/FIFO_Recv.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FIFO_Recv_Msg
+ *
+ * @brief Receiver side for the record oriented C++ wrapper for UNIX FIFOs.
+ */
+class ACE_Export ACE_FIFO_Recv_Msg : public ACE_FIFO_Recv
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FIFO_Recv_Msg (void);
+
+ /// Open up a record-oriented named pipe for reading.
+ ACE_FIFO_Recv_Msg (const ACE_TCHAR *rendezvous,
+ int flags = O_CREAT | O_RDONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Open up a record-oriented named pipe for reading.
+ int open (const ACE_TCHAR *rendezvous,
+ int flags = O_CREAT | O_RDONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ int persistent = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Recv <msg> as an ACE_Str_Buf.
+ ssize_t recv (ACE_Str_Buf &msg);
+
+ /// Recv <msg> as a buffer.
+ ssize_t recv (void *buf, size_t len);
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Recv <data> and <cntl> message via Stream pipes.
+ ssize_t recv (ACE_Str_Buf *data,
+ ACE_Str_Buf *cntl,
+ int *flags);
+
+ /// Recv <data> and <cntl> message via Stream pipes in "band" mode.
+ ssize_t recv (int *band,
+ ACE_Str_Buf *data,
+ ACE_Str_Buf *cntl,
+ int *flags);
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Recv_Msg.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_FIFO_RECV_MSG_H */
diff --git a/ace/IPC/FIFO_Recv_Msg.i b/ace/IPC/FIFO_Recv_Msg.i
new file mode 100644
index 00000000000..e47c0beef3e
--- /dev/null
+++ b/ace/IPC/FIFO_Recv_Msg.i
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FIFO_Recv_Msg.i
+
+// Note that the return values mean different things if
+// ACE_HAS_STREAM_PIPES vs. if it doesn't... See the manual page on
+// getmsg(2) and read(2) for more details.
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv_Msg::recv (ACE_Str_Buf &recv_msg)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::recv");
+#if defined (ACE_HAS_STREAM_PIPES)
+ int i = 0;
+ if (ACE_OS::getmsg (this->get_handle (),
+ (strbuf *) 0,
+ (strbuf *) &recv_msg,
+ &i) == -1)
+ return -1;
+ else
+ return recv_msg.len;
+#else /* Do the ol' 2-read trick... */
+ if (ACE_OS::read (this->get_handle (),
+ (char *) &recv_msg.len,
+ sizeof recv_msg.len) != sizeof recv_msg.len)
+ return -1;
+ else
+ return ACE_OS::read (this->get_handle (),
+ (char *) recv_msg.buf,
+ (int) recv_msg.len);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv_Msg::recv (void *buf, size_t max_len)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::recv");
+ ACE_Str_Buf recv_msg ((char *) buf, 0, max_len);
+
+ return this->recv (recv_msg);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv_Msg::recv (ACE_Str_Buf *data,
+ ACE_Str_Buf *cntl,
+ int *flags)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::recv");
+ if (ACE_OS::getmsg (this->get_handle (),
+ (strbuf *) cntl,
+ (strbuf *) data,
+ flags) == -1)
+ return -1;
+ else
+ return (cntl == 0 ? 0 : cntl->len) + (data == 0 ? 0 : data->len);
+}
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Recv_Msg::recv (int *band,
+ ACE_Str_Buf *data,
+ ACE_Str_Buf *cntl,
+ int *flags)
+{
+ ACE_TRACE ("ACE_FIFO_Recv_Msg::recv");
+ if (ACE_OS::getpmsg (this->get_handle (),
+ (strbuf *) cntl,
+ (strbuf *) data,
+ band,
+ flags) == -1)
+ return -1;
+ else
+ return (cntl == 0 ? 0 : cntl->len) + (data == 0 ? 0 : data->len);
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ace/IPC/FIFO_Send.cpp b/ace/IPC/FIFO_Send.cpp
new file mode 100644
index 00000000000..a51a16f5f96
--- /dev/null
+++ b/ace/IPC/FIFO_Send.cpp
@@ -0,0 +1,53 @@
+// FIFO_Send.cpp
+// $Id$
+
+#include "ace/FIFO_Send.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Send.i"
+#endif
+
+ACE_RCSID(ace, FIFO_Send, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send)
+
+void
+ACE_FIFO_Send::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO_Send::dump");
+ ACE_FIFO::dump ();
+}
+
+ACE_FIFO_Send::ACE_FIFO_Send (void)
+{
+// ACE_TRACE ("ACE_FIFO_Send::ACE_FIFO_Send");
+}
+
+int
+ACE_FIFO_Send::open (const ACE_TCHAR *rendezvous_name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Send::open");
+ return ACE_FIFO::open (rendezvous_name,
+ flags | O_WRONLY,
+ perms,
+ sa);
+}
+
+ACE_FIFO_Send::ACE_FIFO_Send (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Send::ACE_FIFO_Send");
+ if (this->ACE_FIFO_Send::open (fifo_name,
+ flags,
+ perms,
+ sa) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_FIFO_Send::ACE_FIFO_Send")));
+}
diff --git a/ace/IPC/FIFO_Send.h b/ace/IPC/FIFO_Send.h
new file mode 100644
index 00000000000..7c870454b82
--- /dev/null
+++ b/ace/IPC/FIFO_Send.h
@@ -0,0 +1,66 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FIFO_Send.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_FIFO_SEND_H
+#define ACE_FIFO_SEND_H
+#include "ace/pre.h"
+
+#include "ace/FIFO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FIFO_Send
+ *
+ * @brief Sender side for the bytestream C++ wrapper for UNIX FIFOs
+ */
+class ACE_Export ACE_FIFO_Send : public ACE_FIFO
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FIFO_Send (void);
+
+ /// Open up a bytestream named pipe for writing.
+ ACE_FIFO_Send (const ACE_TCHAR *rendezvous,
+ int flags = O_WRONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Open up a bytestream named pipe for writing.
+ int open (const ACE_TCHAR *rendezvous,
+ int flags = O_WRONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Send <buf> of up to <len> bytes.
+ ssize_t send (const void *buf, size_t len);
+
+ /// Send <buf> of exactly <len> bytes (block until done).
+ ssize_t send_n (const void *buf, size_t len);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Send.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_FIFO_SEND_H */
diff --git a/ace/IPC/FIFO_Send.i b/ace/IPC/FIFO_Send.i
new file mode 100644
index 00000000000..c7e20eae8d2
--- /dev/null
+++ b/ace/IPC/FIFO_Send.i
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FIFO_Send.i
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Send::send (const void *buf, size_t len)
+{
+ ACE_TRACE ("ACE_FIFO_Send::send");
+ return ACE_OS::write (this->get_handle (), (const char *) buf, len);
+}
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Send::send_n (const void *buf, size_t n)
+{
+ ACE_TRACE ("ACE_FIFO_Send::send_n");
+ return ACE::send_n (this->get_handle (), buf, n);
+}
diff --git a/ace/IPC/FIFO_Send_Msg.cpp b/ace/IPC/FIFO_Send_Msg.cpp
new file mode 100644
index 00000000000..8d947252002
--- /dev/null
+++ b/ace/IPC/FIFO_Send_Msg.cpp
@@ -0,0 +1,70 @@
+// FIFO_Send_Msg.cpp
+// $Id$
+
+#include "ace/FIFO_Send_Msg.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Send_Msg.i"
+#endif
+
+ACE_RCSID(ace, FIFO_Send_Msg, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send_Msg)
+
+void
+ACE_FIFO_Send_Msg::dump (void) const
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::dump");
+ ACE_FIFO_Send::dump ();
+}
+
+ssize_t
+ACE_FIFO_Send_Msg::send (const ACE_Str_Buf &send_msg)
+{
+ // ACE_TRACE ("ACE_FIFO_Send_Msg::send");
+#if defined (ACE_HAS_STREAM_PIPES)
+ if (ACE_OS::putmsg (this->get_handle (),
+ (strbuf *) 0,
+ (strbuf *) &send_msg,
+ 0) == -1)
+ return -1;
+ else
+ return send_msg.len;
+#else
+ iovec iov[2];
+
+ iov[0].iov_base = (char *) &send_msg.len;
+ iov[0].iov_len = sizeof send_msg.len;
+
+ iov[1].iov_base = (char *) send_msg.buf;
+ iov[1].iov_len = int (send_msg.len);
+
+ return ACE_OS::writev (this->get_handle (), iov, 2);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg (void)
+{
+// ACE_TRACE ("ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg");
+}
+
+int
+ACE_FIFO_Send_Msg::open (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::open");
+ return ACE_FIFO_Send::open (fifo_name, flags | O_WRONLY, perms, sa);
+}
+
+ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg (const ACE_TCHAR *fifo_name,
+ int flags,
+ int perms,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg");
+ if (this->ACE_FIFO_Send_Msg::open (fifo_name, flags, perms, sa) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_FIFO_Send_Msg")));
+}
diff --git a/ace/IPC/FIFO_Send_Msg.h b/ace/IPC/FIFO_Send_Msg.h
new file mode 100644
index 00000000000..cc4ae785e41
--- /dev/null
+++ b/ace/IPC/FIFO_Send_Msg.h
@@ -0,0 +1,80 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FIFO_Send_Msg.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_FIFO_SEND_MSG_H
+#define ACE_FIFO_SEND_MSG_H
+#include "ace/pre.h"
+
+#include "ace/FIFO_Send.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FIFO_Send_Msg
+ *
+ * @brief Sender side for the Record oriented C++ wrapper for UNIX
+ * FIFOs.
+ */
+class ACE_Export ACE_FIFO_Send_Msg : public ACE_FIFO_Send
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FIFO_Send_Msg (void);
+
+ /// Open up a record-oriented named pipe for writing.
+ ACE_FIFO_Send_Msg (const ACE_TCHAR *rendezvous,
+ int flags = O_WRONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Open up a record-oriented named pipe for writing.
+ int open (const ACE_TCHAR *rendezvous,
+ int flags = O_WRONLY,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Send <buf> of up to <len> bytes.
+ ssize_t send (const ACE_Str_Buf &msg);
+
+ /// Send <buf> of exactly <len> bytes (block until done).
+ ssize_t send (const void *buf, size_t len);
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Send <data> and <cntl> message via Stream pipes.
+ ssize_t send (const ACE_Str_Buf *data,
+ const ACE_Str_Buf *cntl = 0,
+ int flags = 0);
+
+ /// Send <data> and <cntl> message via Stream pipes in "band" mode.
+ ssize_t send (int band,
+ const ACE_Str_Buf *data,
+ const ACE_Str_Buf *cntl = 0,
+ int flags = MSG_BAND);
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FIFO_Send_Msg.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_FIFO_SEND_MSG_H */
diff --git a/ace/IPC/FIFO_Send_Msg.i b/ace/IPC/FIFO_Send_Msg.i
new file mode 100644
index 00000000000..07b7de5e195
--- /dev/null
+++ b/ace/IPC/FIFO_Send_Msg.i
@@ -0,0 +1,48 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FIFO_Send_Msg.i
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Send_Msg::send (const void *buf, size_t len)
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::send");
+ ACE_Str_Buf send_msg ((char *) buf, len);
+
+ return this->send (send_msg);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ASYS_INLINE ssize_t
+ACE_FIFO_Send_Msg::send (const ACE_Str_Buf *data,
+ const ACE_Str_Buf *cntl,
+ int flags)
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::send");
+ if (ACE_OS::putmsg (this->get_handle (),
+ (strbuf *) cntl,
+ (strbuf *) data,
+ flags) == -1)
+ return-1;
+ else
+ return (cntl == 0 ? 0 : cntl->len) + (data == 0 ? 0 : data->len);
+}
+
+ASYS_INLINE ssize_t
+ACE_FIFO_Send_Msg::send (int band,
+ const ACE_Str_Buf *data,
+ const ACE_Str_Buf *cntl,
+ int flags)
+{
+ ACE_TRACE ("ACE_FIFO_Send_Msg::send");
+
+ if (ACE_OS::putpmsg (this->get_handle (),
+ (strbuf *) cntl,
+ (strbuf *) data,
+ band,
+ flags) == -1)
+ return -1;
+ else
+ return (cntl == 0 ? 0 : cntl->len) + (data == 0 ? 0 : data->len);
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ace/IPC/FILE.cpp b/ace/IPC/FILE.cpp
new file mode 100644
index 00000000000..1c031eaa049
--- /dev/null
+++ b/ace/IPC/FILE.cpp
@@ -0,0 +1,151 @@
+// FILE.cpp
+// $Id$
+
+/* Defines the member functions for the base class of the ACE_IO_SAP
+ ACE_FILE abstraction. */
+
+#include "ace/FILE.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE.i"
+#endif
+
+ACE_RCSID(ace, FILE, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE)
+
+void
+ACE_FILE::dump (void) const
+{
+ ACE_TRACE ("ACE_FILE::dump");
+ ACE_IO_SAP::dump ();
+}
+
+// This is the do-nothing constructor.
+
+ACE_FILE::ACE_FILE (void)
+{
+ ACE_TRACE ("ACE_FILE::ACE_FILE");
+}
+
+// Close the file
+
+int
+ACE_FILE::close (void)
+{
+ ACE_TRACE ("ACE_FILE::close");
+ int result = ACE_OS::close (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ return result;
+}
+
+int
+ACE_FILE::get_info (ACE_FILE_Info *finfo)
+{
+ ACE_TRACE ("ACE_FILE::get_info");
+ ACE_stat filestatus;
+
+ int result = ACE_OS::fstat (this->get_handle (),
+ &filestatus);
+
+ if (result == 0)
+ {
+ finfo->mode_ = filestatus.st_mode;
+ finfo->nlink_ = filestatus.st_nlink;
+ finfo->size_ = filestatus.st_size;
+ }
+
+ return result;
+}
+
+int
+ACE_FILE::get_info (ACE_FILE_Info &finfo)
+{
+ ACE_TRACE ("ACE_FILE::get_info");
+
+ return this->get_info (&finfo);
+}
+
+int
+ACE_FILE::truncate (off_t length)
+{
+ ACE_TRACE ("ACE_FILE::truncate");
+ return ACE_OS::ftruncate (this->get_handle(), length);
+}
+
+off_t
+ACE_FILE::seek (off_t offset, int startpos)
+{
+ return ACE_OS::lseek (this->get_handle (),
+ offset,
+ startpos);
+}
+
+off_t
+ACE_FILE::position (long offset, int startpos)
+{
+ ACE_TRACE ("ACE_FILE::position");
+ return this->seek (offset, startpos);
+}
+
+off_t
+ACE_FILE::tell (void)
+{
+ ACE_TRACE ("ACE_FILE::tell");
+ return ACE_OS::lseek (this->get_handle (), 0, SEEK_CUR);
+}
+
+off_t
+ACE_FILE::position (void)
+{
+ ACE_TRACE ("ACE_FILE::position");
+ return this->tell ();
+}
+
+// Return the local endpoint address.
+
+int
+ACE_FILE::get_local_addr (ACE_Addr &addr) const
+{
+ ACE_TRACE ("ACE_FILE::get_local_addr");
+
+ // Perform the downcast since <addr> had better be an
+ // <ACE_FILE_Addr>.
+ ACE_FILE_Addr *file_addr =
+ ACE_dynamic_cast (ACE_FILE_Addr *, &addr);
+
+ if (file_addr == 0)
+ return -1;
+ else
+ {
+ *file_addr = this->addr_;
+ return 0;
+ }
+}
+
+// Return the same result as <get_local_addr>.
+
+int
+ACE_FILE::get_remote_addr (ACE_Addr &addr) const
+{
+ ACE_TRACE ("ACE_FILE::get_remote_addr");
+
+ return this->get_local_addr (addr);
+}
+
+int
+ACE_FILE::remove (void)
+{
+ ACE_TRACE ("ACE_FILE::remove");
+
+ this->close ();
+ return ACE_OS::unlink (this->addr_.get_path_name ());
+}
+
+int
+ACE_FILE::unlink (void)
+{
+ ACE_TRACE ("ACE_FILE::unlink");
+
+ return ACE_OS::unlink (this->addr_.get_path_name ());
+}
diff --git a/ace/IPC/FILE.h b/ace/IPC/FILE.h
new file mode 100644
index 00000000000..e9fbfc1d749
--- /dev/null
+++ b/ace/IPC/FILE.h
@@ -0,0 +1,140 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FILE.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ */
+//=============================================================================
+
+#ifndef ACE_FILE_H
+#define ACE_FILE_H
+#include "ace/pre.h"
+
+#include "ace/IO_SAP.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/FILE_Addr.h"
+
+// The following is necessary since many C++ compilers don't support
+// typedef'd types inside of classes used as formal template
+// arguments... ;-(. Luckily, using the C++ preprocessor I can hide
+// most of this nastiness!
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+#define ACE_FILE_CONNECTOR ACE_FILE_Connector
+#define ACE_FILE_STREAM ACE_FILE_IO
+#else /* TEMPLATES are broken (must be a cfront-based compiler...) */
+#define ACE_FILE_CONNECTOR ACE_FILE_Connector, ACE_FILE_Addr
+#define ACE_FILE_STREAM ACE_FILE_IO, ACE_FILE_Addr
+#endif /* ACE_TEMPLATE_TYPEDEFS */
+
+/**
+ * @class ACE_FILE_Info
+ *
+ * @brief Abstracts basic OS FILE information.
+ */
+class ACE_Export ACE_FILE_Info
+{
+public:
+ /// mode of file
+ mode_t mode_;
+
+ /// no of links
+ nlink_t nlink_;
+
+ /// size of file
+ off_t size_;
+};
+
+/**
+ * @class ACE_FILE
+ *
+ * @brief Defines the core methods of the <ACE_FILE> abstraction.
+ */
+class ACE_Export ACE_FILE : public ACE_IO_SAP
+{
+public:
+ /// Close the <ACE_FILE> handle without removing the <ACE_FILE> from
+ /// the file system.
+ int close (void);
+
+ /// Close and remove the <ACE_FILE> from the file system.
+ int remove (void);
+
+ /// Remove the <ACE_FILE> from the file system without closing the
+ /// <ACE_FILE> handle.
+ int unlink (void);
+
+ /// Get information on this <ACE_FILE>.
+ int get_info (ACE_FILE_Info *finfo);
+
+ /// Get information on this <ACE_FILE>.
+ int get_info (ACE_FILE_Info &finfo);
+
+ /// Set filesize to length byte.
+ int truncate (off_t length);
+
+ /**
+ * Sets the file pointer as follows:
+ * o If <whence> is <SEEK_SET>, the pointer is set to <offset>
+ * bytes.
+ *
+ * o If <whence> is <SEEK_CUR>, the pointer is set to its
+ * current location plus <offset>.
+ *
+ * o If <whence> is <SEEK_END>, the pointer is set to the size
+ * of the file plus offset.
+ * Same as <seek>, but <position> is deprecated.
+ */
+ off_t seek (off_t offset,
+ int whence = SEEK_CUR);
+ off_t position (long offset, int startpos);
+
+ /// Return an offset for the file handle.
+ off_t tell (void);
+
+ /// Same as <tell>, but <position> is deprecated.
+ off_t position (void);
+
+ /**
+ * Disable signal <signum>
+ * This is here to prevent Win32 from
+ * disabling SPIPE using socket calls
+ */
+ int disable (int signum) const ;
+
+ /// Return the local endpoint address in the referenced <ACE_Addr>.
+ /// Returns 0 if successful, else -1.
+ int get_local_addr (ACE_Addr &) const;
+
+ /// Return the same thing as <get_local_addr>.
+ int get_remote_addr (ACE_Addr &) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Ensure that this class is only created by the
+ /// <ACE_FILE_Connector>.
+ ACE_FILE (void);
+
+ /// File we are "connected" with...
+ ACE_FILE_Addr addr_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_FILE_H */
diff --git a/ace/IPC/FILE.i b/ace/IPC/FILE.i
new file mode 100644
index 00000000000..cf1f4986479
--- /dev/null
+++ b/ace/IPC/FILE.i
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FILE.i
+
+ASYS_INLINE int
+ACE_FILE::disable (int signum) const
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (signum) ;
+ return 0 ;
+#else /* ACE_WIN32 */
+ return ACE_IO_SAP::disable (signum) ;
+#endif /* ACE_WIN32 */
+}
+
diff --git a/ace/IPC/FILE_Addr.cpp b/ace/IPC/FILE_Addr.cpp
new file mode 100644
index 00000000000..cc7c47743ec
--- /dev/null
+++ b/ace/IPC/FILE_Addr.cpp
@@ -0,0 +1,110 @@
+// $Id$
+
+#include "ace/FILE_Addr.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/FILE_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, FILE_Addr, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE_Addr)
+
+ACE_FILE_Addr::ACE_FILE_Addr (void)
+ : ACE_Addr (AF_FILE, sizeof this->filename_ / sizeof (ACE_TCHAR))
+{
+ this->filename_[0] = '\0';
+}
+
+int
+ACE_FILE_Addr::set (const ACE_FILE_Addr &sa)
+{
+ if (sa.get_type () == AF_ANY)
+ {
+#if defined (ACE_DEFAULT_TEMP_FILE)
+ // Create a temporary file.
+ ACE_OS::strcpy (this->filename_,
+ ACE_DEFAULT_TEMP_FILE);
+#else /* ACE_DEFAULT_TEMP_FILE */
+ if (ACE_Lib_Find::get_temp_dir (this->filename_,
+ MAXPATHLEN - 15) == -1)
+ // -15 for ace-file-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Temporary path too long, ")
+ ACE_LIB_TEXT ("defaulting to current directory\n")));
+ this->filename_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->filename_, ACE_LIB_TEXT ("ace-file-XXXXXX"));
+
+#endif /* ACE_DEFAULT_TEMP_FILE */
+
+ ACE_OS::mktemp (this->filename_);
+ this->base_set (AF_FILE,
+ ACE_OS::strlen (this->filename_) + 1);
+ }
+ else
+ {
+ (void) ACE_OS::strsncpy (this->filename_,
+ sa.filename_,
+ sa.get_size ());
+
+ this->base_set (sa.get_type (),
+ sa.get_size ());
+ }
+ return 0;
+}
+
+// Copy constructor.
+
+ACE_FILE_Addr::ACE_FILE_Addr (const ACE_FILE_Addr &sa)
+ : ACE_Addr (AF_FILE, sizeof this->filename_)
+{
+ this->set (sa);
+}
+
+int
+ACE_FILE_Addr::set (const ACE_TCHAR *filename)
+{
+ this->ACE_Addr::base_set (AF_FILE,
+ ACE_OS::strlen (filename) + 1);
+ (void) ACE_OS::strsncpy (this->filename_,
+ filename,
+ sizeof this->filename_ / sizeof (ACE_TCHAR));
+ return 0;
+}
+
+ACE_FILE_Addr &
+ACE_FILE_Addr::operator= (const ACE_FILE_Addr &sa)
+{
+ if (this != &sa)
+ this->set (sa);
+ return *this;
+}
+
+// Create a ACE_Addr from a ACE_FILE pathname.
+
+ACE_FILE_Addr::ACE_FILE_Addr (const ACE_TCHAR *filename)
+{
+ this->set (filename);
+}
+
+int
+ACE_FILE_Addr::addr_to_string (ACE_TCHAR *s, size_t len) const
+{
+ ACE_OS::strsncpy (s, this->filename_, len);
+ return 0;
+}
+
+void
+ACE_FILE_Addr::dump (void) const
+{
+ ACE_TRACE ("ACE_FILE_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("filename_ = %s"), this->filename_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
diff --git a/ace/IPC/FILE_Addr.h b/ace/IPC/FILE_Addr.h
new file mode 100644
index 00000000000..b0307e6f856
--- /dev/null
+++ b/ace/IPC/FILE_Addr.h
@@ -0,0 +1,85 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FILE_Addr.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_FILE_ADDR_H
+#define ACE_FILE_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Flag_Manip.h"
+
+/**
+ * @class ACE_FILE_Addr
+ *
+ * @brief Defines the FILE address family address format.
+ */
+class ACE_Export ACE_FILE_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FILE_Addr (void);
+
+ /// Copy constructor.
+ ACE_FILE_Addr (const ACE_FILE_Addr &sa);
+
+ /// Acts like a copy constructor. If <sa> == ACE_Addr::sap_any then
+ /// create a temporary filename using <ACE_OS::mktemp>.
+ int set (const ACE_FILE_Addr &sa);
+
+ /// Create a ACE_FILE_Addr from a pathname.
+ ACE_EXPLICIT ACE_FILE_Addr (const ACE_TCHAR *filename);
+
+ /// Create a ACE_FILE_Addr from a pathname.
+ int set (const ACE_TCHAR *filename);
+
+ /// Assignment operator.
+ ACE_FILE_Addr &operator= (const ACE_FILE_Addr &);
+
+ /// Return a pointer to the address.
+ virtual void *get_addr (void) const;
+
+ /// Transform the current address into string format.
+ virtual int addr_to_string (ACE_TCHAR *addr, size_t) const;
+
+ /// Compare two addresses for equality.
+ int operator == (const ACE_FILE_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ int operator != (const ACE_FILE_Addr &SAP) const;
+
+ /// Return the path name used for the rendezvous point.
+ const ACE_TCHAR *get_path_name (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Name of the file.
+ ACE_TCHAR filename_[MAXNAMLEN + 1];
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/FILE_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_FILE_ADDR_H */
diff --git a/ace/IPC/FILE_Addr.i b/ace/IPC/FILE_Addr.i
new file mode 100644
index 00000000000..6acce0515b8
--- /dev/null
+++ b/ace/IPC/FILE_Addr.i
@@ -0,0 +1,43 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FILE_Addr.i
+
+// Do nothing constructor.
+
+// Transform the current address into string format.
+
+#include "ace/SString.h"
+
+// Return the address.
+
+ACE_INLINE void *
+ACE_FILE_Addr::get_addr (void) const
+{
+ return (void *) &this->filename_;
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE int
+ACE_FILE_Addr::operator == (const ACE_FILE_Addr &sap) const
+{
+ return ACE_OS::strcmp (this->filename_, sap.filename_) == 0;
+}
+
+// Compare two addresses for inequality.
+
+ACE_INLINE int
+ACE_FILE_Addr::operator != (const ACE_FILE_Addr &sap) const
+{
+ return !((*this) == sap); // This is lazy, of course... ;-)
+}
+
+// Return the path name used for the rendezvous point.
+
+ACE_INLINE const ACE_TCHAR *
+ACE_FILE_Addr::get_path_name (void) const
+{
+ return this->filename_;
+}
+
diff --git a/ace/IPC/FILE_Connector.cpp b/ace/IPC/FILE_Connector.cpp
new file mode 100644
index 00000000000..d858fc68c5f
--- /dev/null
+++ b/ace/IPC/FILE_Connector.cpp
@@ -0,0 +1,84 @@
+// FILE_Connector.cpp
+// $Id$
+
+#include "ace/FILE_Connector.h"
+#include "ace/Handle_Ops.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE_Connector.i"
+#endif
+
+ACE_RCSID(ace, FILE_Connector, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE_Connector)
+
+void
+ACE_FILE_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_FILE_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_FILE_Connector::ACE_FILE_Connector (void)
+{
+ ACE_TRACE ("ACE_FILE_Connector::ACE_FILE_Connector");
+}
+
+int
+ACE_FILE_Connector::connect (ACE_FILE_IO &new_io,
+ const ACE_FILE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &,
+ int,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_FILE_Connector::connect");
+ ACE_ASSERT (new_io.get_handle () == ACE_INVALID_HANDLE);
+
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+
+ // Check to see if caller has requested that we create the filename.
+ if (ACE_reinterpret_cast (const ACE_Addr &,
+ ACE_const_cast (ACE_FILE_Addr &,
+ remote_sap)) == ACE_Addr::sap_any)
+ {
+ // Create a new temporary file.
+#ifdef ACE_LACKS_MKSTEMP
+ new_io.addr_ =
+ ACE_FILE_Addr (ACE_sap_any_cast (ACE_FILE_Addr &)); // class copy.
+#else
+ // Use ACE_OS::mkstemp() if it is available since it avoids a
+ // race condition, and subsequently a security hole due to that
+ // race condition (specifically, a denial-of-service attack).
+ //
+ // However, using mkstemp() prevents us from doing a timed open
+ // since it opens the file for us. Better to avoid the race
+ // condition.
+ char filename[] = "ace-file-XXXXXX";
+
+ handle = ACE_OS::mkstemp (filename); // mkstemp() replaces "XXXXXX"
+
+ if (handle == ACE_INVALID_HANDLE
+ || new_io.addr_.set (filename) != 0)
+ return -1;
+
+ new_io.set_handle (handle);
+
+ return 0;
+#endif /* ACE_LACKS_MKSTEMP */
+ }
+ else
+ new_io.addr_ = remote_sap; // class copy.
+
+ handle = ACE_Handle_Ops::handle_timed_open (timeout,
+ new_io.addr_.get_path_name (),
+ flags,
+ perms);
+
+ new_io.set_handle (handle);
+ return handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
diff --git a/ace/IPC/FILE_Connector.h b/ace/IPC/FILE_Connector.h
new file mode 100644
index 00000000000..859872b45d1
--- /dev/null
+++ b/ace/IPC/FILE_Connector.h
@@ -0,0 +1,110 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FILE_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_FILE_CONNECTOR_H
+#define ACE_FILE_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/FILE_IO.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_FILE_Connector
+ *
+ * @brief Defines an active connection factory for the ACE_FILE wrappers.
+ *
+ * Note that the O_APPEND flag is only partly supported on Win32. If
+ * you specify O_APPEND, then the file pointer will be positioned at
+ * the end of the file initially during open, but it is not
+ * re-positioned at the end prior to each write, as specified by
+ * POSIX. This is generally good enough for typical situations, but
+ * it is ``not quite right'' in its semantics.
+ */
+class ACE_Export ACE_FILE_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_FILE_Connector (void);
+
+ /**
+ * Actively ``connect'' and produce a <new_io> <ACE_FILE_IO> object
+ * if things go well. The <remote_sap> is the file that we are
+ * trying to create/open. If it's the default value of
+ * <ACE_Addr::sap_any> then the user is letting the OS create the
+ * filename (via <ACE_OS::mktemp>). The <timeout> is the amount of
+ * time to wait to create/open the file. If it's 0 then we block
+ * indefinitely. If *timeout == {0, 0} then the file is created
+ * using non-blocking mode. In this case, if the create/open can't
+ * be done immediately the value of -1 is returned with <errno ==
+ * EWOULDBLOCK>. If *timeout > {0, 0} then this is the maximum amount of
+ * time to wait before timing out. If the time expires before the
+ * connection is made <errno == ETIME>. The <local_sap> and
+ * <reuse_addr> parameters are ignored. The <flags> and <perms>
+ * arguments are passed down to the <ACE_OS::open> method.
+ */
+ ACE_FILE_Connector (ACE_FILE_IO &new_io,
+ const ACE_FILE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR | O_CREAT,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /**
+ * Actively ``connect'' and produce a <new_io> <ACE_FILE_IO> object
+ * if things go well. The <remote_sap> is the file that we are
+ * trying to create/open. If it's the default value of
+ * <ACE_Addr::sap_any> then the user is letting the OS create the
+ * filename (via <ACE_OS::mktemp>). The <timeout> is the amount of
+ * time to wait to create/open the file. If it's 0 then we block
+ * indefinitely. If *timeout == {0, 0} then the file is created
+ * using non-blocking mode. In this case, if the create/open can't
+ * be done immediately the value of -1 is returned with <errno ==
+ * EWOULDBLOCK>. If *timeout > {0, 0} then this is the maximum amount of
+ * time to wait before timing out. If the time expires before the
+ * connection is made <errno == ETIME>. The <local_sap> and
+ * <reuse_addr> parameters are ignored. The <flags> and <perms>
+ * arguments are passed down to the <ACE_OS::open> method.
+ */
+ int connect (ACE_FILE_IO &new_io,
+ const ACE_FILE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR | O_CREAT,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Meta-type "trait" information.
+ typedef ACE_FILE_Addr PEER_ADDR;
+ typedef ACE_FILE_IO PEER_STREAM;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE_Connector.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_FILE_CONNECTOR_H */
diff --git a/ace/IPC/FILE_Connector.i b/ace/IPC/FILE_Connector.i
new file mode 100644
index 00000000000..ccb5985899f
--- /dev/null
+++ b/ace/IPC/FILE_Connector.i
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FILE_Connector.i
+
+// Creates a Local ACE_FILE.
+
+ASYS_INLINE
+ACE_FILE_Connector::ACE_FILE_Connector (ACE_FILE_IO &new_io,
+ const ACE_FILE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_FILE_Connector::ACE_FILE_Connector");
+ if (this->connect (new_io, remote_sap, timeout, local_sap,
+ reuse_addr, flags, perms) == ACE_IO_SAP::INVALID_HANDLE
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (),
+ ACE_LIB_TEXT ("ACE_FILE_IO")));
+}
+
+ASYS_INLINE int
+ACE_FILE_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_UNUSED_ARG (handle);
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
diff --git a/ace/IPC/FILE_IO.cpp b/ace/IPC/FILE_IO.cpp
new file mode 100644
index 00000000000..de7400f3c82
--- /dev/null
+++ b/ace/IPC/FILE_IO.cpp
@@ -0,0 +1,133 @@
+// FILE_IO.cpp
+// $Id$
+
+#include "ace/FILE_IO.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE_IO.i"
+#endif
+
+ACE_RCSID(ace, FILE_IO, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_FILE_IO)
+
+void
+ACE_FILE_IO::dump (void) const
+{
+ ACE_TRACE ("ACE_FILE_IO::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Simple-minded do nothing constructor.
+
+ACE_FILE_IO::ACE_FILE_IO (void)
+{
+ ACE_TRACE ("ACE_FILE_IO::ACE_FILE_IO");
+}
+
+// Send N char *ptrs and int lengths. Note that the char *'s precede
+// the ints (basically, an varargs version of writev). The count N is
+// the *total* number of trailing arguments, *not* a couple of the
+// number of tuple pairs!
+
+ssize_t
+ACE_FILE_IO::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::writev (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// This is basically an interface to ACE_OS::readv, that doesn't use
+// the struct iovec explicitly. The ... can be passed as an arbitrary
+// number of (char *ptr, int len) tuples. However, the count N is the
+// *total* number of trailing arguments, *not* a couple of the number
+// of tuple pairs!
+
+ssize_t
+ACE_FILE_IO::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::readv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// Allows a client to read from a file without having to provide a
+// buffer to read. This method determines how much data is in the
+// file, allocates a buffer of this size, reads in the data, and
+// returns the number of bytes read.
+
+ssize_t
+ACE_FILE_IO::recvv (iovec *io_vec)
+{
+ ACE_TRACE ("ACE_FILE_IO::recvv");
+
+ io_vec->iov_base = 0;
+ long length = ACE_OS::filesize (this->get_handle ());
+
+ if (length > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[length],
+ -1);
+ io_vec->iov_len = this->recv_n (io_vec->iov_base,
+ length);
+ return io_vec->iov_len;
+ }
+ else
+ return length;
+}
diff --git a/ace/IPC/FILE_IO.h b/ace/IPC/FILE_IO.h
new file mode 100644
index 00000000000..b4060da77aa
--- /dev/null
+++ b/ace/IPC/FILE_IO.h
@@ -0,0 +1,160 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file FILE_IO.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_FILE_IO_H
+#define ACE_FILE_IO_H
+#include "ace/pre.h"
+
+#include "ace/FILE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/FILE_Addr.h"
+
+// Used in the FILE_IO.h file...
+#include "ace/ACE.h"
+
+// Forward decl.
+class ACE_Message_Block;
+
+/**
+ * @class ACE_FILE_IO
+ *
+ * @brief Read/Write operations on Files
+ */
+class ACE_Export ACE_FILE_IO : public ACE_FILE
+{
+public:
+ friend class ACE_FILE_Connector;
+
+ // = Initialization method.
+ /// Default constructor.
+ ACE_FILE_IO (void);
+
+ /// send upto <n> bytes in <buf>.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv upto <n> bytes in <buf>.
+ ssize_t recv (void *buf, size_t n) const;
+
+ /// Send n bytes, keep trying until n are sent.
+ ssize_t send_n (const void *buf, size_t n) const;
+
+ /// Send all the <message_block>s chained through their <next> and
+ /// <cont> pointers. This call uses the underlying OS gather-write
+ /// operation to reduce the domain-crossing penalty.
+ ssize_t send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0);
+
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t recv_n (void *buf, size_t n) const;
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ /// Send bytes via STREAM pipes.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int flags = 0) const;
+
+ /// Recv bytes via STREAM pipes.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *flags) const;
+
+ /// Send bytes via STREAM pipes using "band" mode.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int band,
+ int flags) const;
+
+ /// Recv bytes via STREAM pipes using "band" mode.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *band,
+ int *flags) const;
+
+#endif /* ACE_HAS_STREAM_PIPES */
+
+ /// Send iovecs via <::writev>.
+ ssize_t send (const iovec iov[], size_t n) const;
+
+ /// Recv iovecs via <::readv>.
+ ssize_t recv (iovec iov[], size_t n) const;
+
+ /**
+ * Send N char *ptrs and int lengths. Note that the char *'s
+ * precede the ints (basically, an varargs version of writev). The
+ * count N is the *total* number of trailing arguments, *not* a
+ * couple of the number of tuple pairs!
+ */
+ ssize_t send (size_t n, ...) const;
+
+ /**
+ * This is an interface to ::readv, that doesn't use the struct
+ * iovec explicitly. The ... can be passed as an arbitrary number
+ * of (char *ptr, int len) tuples. However, the count N is the
+ * *total* number of trailing arguments, *not* a couple of the
+ * number of tuple pairs!
+ */
+ ssize_t recv (size_t n, ...) const;
+
+ /// Send <n> bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv <n> bytes via Win32 ReadFile using overlapped I/O.
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an <iovec> of size <n> to the file.
+ ssize_t sendv (const iovec iov[],
+ size_t n) const;
+
+ /**
+ * Allows a client to read from a file without having to provide a
+ * buffer to read. This method determines how much data is in the
+ * file, allocates a buffer of this size, reads in the data, and
+ * returns the number of bytes read. The caller is responsible for
+ * deleting the member in the <iov_base> field of <io_vec> using
+ * delete [] io_vec->iov_base.
+ */
+ ssize_t recvv (iovec *io_vec);
+
+ /// Send an <iovec> of size <n> to the file. Will block until all
+ /// bytes are sent or an error occurs.
+ ssize_t sendv_n (const iovec iov[],
+ size_t n) const;
+
+ /// Receive an <iovec> of size <n> to the file.
+ ssize_t recvv_n (iovec iov[],
+ size_t n) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ // = Meta-type info
+ typedef ACE_FILE_Addr PEER_ADDR;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/FILE_IO.i"
+#endif /* !defined (ACE_LACKS_INLINE_FUNCTIONS) */
+
+#include "ace/post.h"
+#endif /* ACE_FILE_IO_H */
diff --git a/ace/IPC/FILE_IO.i b/ace/IPC/FILE_IO.i
new file mode 100644
index 00000000000..a00d6aef8ba
--- /dev/null
+++ b/ace/IPC/FILE_IO.i
@@ -0,0 +1,145 @@
+/* -*- C++ -*- */
+// $Id$
+
+// FILE_IO.i
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::sendv_n (const iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::sendv_n");
+ return ACE::writev_n (this->get_handle (),
+ iov,
+ n);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred)
+{
+ ACE_TRACE ("ACE_FILE_IO::send_n");
+ ACE_UNUSED_ARG (timeout);
+ return ACE::write_n (this->get_handle (),
+ message_block,
+ bytes_transferred);
+}
+
+// Recv an n byte message from the file.
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recvv_n (iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recvv_n");
+ // @@ Carlos, can you please update this to call the
+ // new ACE::recvv_n() method that you write?
+ return ACE_OS::readv (this->get_handle (),
+ iov,
+ n);
+}
+
+// Send an <iovec> of size <n> to the file.
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::sendv (const iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::sendv");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+// Send exactly N bytes from BUF to this file. Keeping trying until
+// this many bytes are sent.
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send_n (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send_n");
+ return ACE::write_n (this->get_handle (), buf, n);
+}
+
+// Receive exactly N bytes from this file into BUF. Keep trying until
+// this many bytes are received.
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv_n (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv_n");
+ return ACE::read_n (this->get_handle (), buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::write (this->get_handle (), (const char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send (const iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv (iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::readv (this->get_handle (), iov, n);
+}
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::send (const void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_FILE_IO::send");
+ return ACE_OS::write (this->get_handle (),
+ (const char *) buf, n,
+ overlapped);
+}
+
+ASYS_INLINE ssize_t
+ACE_FILE_IO::recv (void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_FILE_IO::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, n,
+ overlapped);
+}
+
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ace/IPC/INET_Addr.cpp b/ace/IPC/INET_Addr.cpp
new file mode 100644
index 00000000000..d77067f2465
--- /dev/null
+++ b/ace/IPC/INET_Addr.cpp
@@ -0,0 +1,935 @@
+// $Id$
+
+// Defines the Internet domain address family address format.
+
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/INET_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, INET_Addr, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_INET_Addr)
+
+// Transform the current address into string format.
+
+int
+ACE_INET_Addr::addr_to_string (ACE_TCHAR s[],
+ size_t size,
+ int ipaddr_format) const
+{
+ ACE_TRACE ("ACE_INET_Addr::addr_to_string");
+
+ // XXX Can we (should we) include the scope id for IPv6 addresses?
+
+ size_t total_len = (ipaddr_format == 0 ?
+ ACE_OS::strlen (this->get_host_name ()) :
+ ACE_OS::strlen (this->get_host_addr ()))
+ + ACE_OS::strlen ("65536") // Assume the max port number.
+ + sizeof (':')
+#if defined ACE_HAS_IPV6
+ + ACE_OS::strlen ("[]")
+#endif
+ + sizeof ('\0'); // For trailing '\0'.
+
+ if (size < total_len)
+ return -1;
+ else
+ {
+ ACE_OS::sprintf (s,
+#if defined ACE_HAS_IPV6
+ ACE_LIB_TEXT ("[%s]:%d"),
+#else
+ ACE_LIB_TEXT ("%s:%d"),
+#endif
+ ACE_TEXT_CHAR_TO_TCHAR (ipaddr_format == 0
+ ? this->get_host_name ()
+ : this->get_host_addr ()),
+ this->get_port_number ());
+ return 0;
+ }
+}
+
+void
+ACE_INET_Addr::dump (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ ACE_TCHAR s[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16];
+ this->addr_to_string(s, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16);
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("%s"), s));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Compare two addresses for inequality.
+
+int
+ACE_INET_Addr::operator != (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_INET_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+// Compare two addresses for equality.
+
+int
+ACE_INET_Addr::operator == (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_INET_Addr::operator ==");
+
+ if (this->get_type () != sap.get_type () ||
+ this->get_size () != sap.get_size () )
+ return 0;
+
+ return (ACE_OS::memcmp (&this->inet_addr_,
+ &sap.inet_addr_,
+ this->get_size ()) == 0);
+}
+
+ACE_INET_Addr::ACE_INET_Addr (void)
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ // ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ (void) ACE_OS::memset ((void *) &this->inet_addr_,
+ 0,
+ sizeof this->inet_addr_);
+}
+
+int
+ACE_INET_Addr::set (const ACE_INET_Addr &sa)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+
+ if (sa.get_type () == AF_ANY)
+ // Ugh, this is really a base class, so don't copy it.
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ else
+ // It's ok to make the copy.
+ ACE_OS::memcpy (&this->inet_addr_, &sa.inet_addr_, sa.get_size ());
+
+ return 0;
+}
+
+// Transform the string into the current addressing format.
+
+int
+ACE_INET_Addr::string_to_addr (const char s[])
+{
+ ACE_TRACE ("ACE_INET_Addr::string_to_addr");
+ int result;
+ char *ip_addr;
+
+ // Need to make a duplicate since we'll be overwriting the string.
+ ACE_ALLOCATOR_RETURN (ip_addr,
+ ACE_OS::strdup (s),
+ -1);
+ // We use strrchr because of IPv6 addresses.
+ char *port_p = ACE_OS::strrchr (ip_addr, ':');
+
+ if (port_p == 0) // Assume it's a port number.
+ {
+ if (ACE_OS::strspn (ip_addr, "1234567890") == ACE_OS::strlen (ip_addr))
+ { // port number
+ u_short port = (u_short) ACE_OS::atoi (ip_addr);
+ result = this->set (port, ACE_UINT32 (INADDR_ANY));
+ }
+ else // port name
+ result = this->set (ip_addr, ACE_UINT32 (INADDR_ANY));
+ }
+ else
+ {
+ *port_p = '\0'; ++port_p; // skip over ':'
+
+ if (ACE_OS::strspn (port_p, "1234567890") == ACE_OS::strlen (port_p))
+ {
+ u_short port = (u_short) ACE_OS::atoi (port_p);
+ result = this->set (port, ip_addr);
+ }
+ else
+ result = this->set (port_p, ip_addr);
+ }
+
+ ACE_OS::free (ACE_MALLOC_T (ip_addr));
+ return result;
+}
+
+int
+ACE_INET_Addr::set (const char address[])
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+ return this->string_to_addr (address);
+}
+
+ACE_INET_Addr::ACE_INET_Addr (const char address[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ this->set (address);
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INET_Addr::ACE_INET_Addr (const wchar_t address[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ this->set (address);
+}
+
+#endif /* ACE_HAS_WCHAR */
+
+// Copy constructor.
+
+ACE_INET_Addr::ACE_INET_Addr (const ACE_INET_Addr &sa)
+ : ACE_Addr (sa.get_type (), sa.get_size())
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->set (sa);
+}
+
+// Initializes a ACE_INET_Addr from a PORT_NUMBER and a 32 bit Internet
+// address.
+
+int
+ACE_INET_Addr::set (u_short port_number,
+ ACE_UINT32 inet_address,
+ int encode)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+ this->set_address (ACE_reinterpret_cast (const char *, &inet_address),
+ sizeof inet_address,
+ encode);
+ this->set_port_number (port_number, encode);
+
+ return 0;
+}
+
+
+// Initializes a ACE_INET_Addr from a PORT_NUMBER and the remote
+// HOST_NAME.
+
+int
+ACE_INET_Addr::set (u_short port_number,
+ const char host_name[],
+ int encode,
+ int address_family)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+
+ // Yow, someone gave us a NULL host_name!
+ if (host_name == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ACE_OS_String::memset ((void *) &this->inet_addr_,
+ 0,
+ sizeof this->inet_addr_);
+
+#if defined (ACE_HAS_IPV6)
+ struct addrinfo hints, *res, *res0;
+ int error;
+ ACE_OS_String::memset (&hints, 0, sizeof (hints));
+
+ hints.ai_family = address_family;
+
+ error = getaddrinfo (host_name, 0, &hints, &res0);
+ if (error)
+ return -1;
+
+ int ret = -1;
+ for (res = res0; res != 0; res = res->ai_next)
+ {
+ if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
+ {
+ this->set_type (res->ai_family);
+ this->set_addr (res->ai_addr, res->ai_addrlen);
+ this->set_port_number (port_number, encode);
+ ret = 0;
+ break;
+ }
+ }
+ freeaddrinfo (res0);
+ return ret;
+
+#else /* ACE_HAS_IPV6 */
+
+ // IPv6 not supported... insure the family is set to IPv4
+ address_family = AF_INET;
+ this->set_type (address_family);
+ this->inet_addr_.in4_.sin_family = address_family;
+ struct in_addr addrv4;
+ if (ACE_OS::inet_aton (host_name,
+ &addrv4) == 1)
+ return this->set (port_number,
+ encode ? ntohl (addrv4.s_addr) : addrv4.s_addr,
+ encode);
+ else
+ {
+# if defined (VXWORKS) || defined (CHORUS)
+ hostent *hp = ACE_OS::gethostbyname (host_name);
+# else
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ int error;
+
+ hostent *hp = ACE_OS::gethostbyname_r (host_name, &hentry,
+ buf, &error);
+# endif /* VXWORKS */
+
+ if (hp == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ (void) ACE_OS_String::memcpy ((void *) &addrv4.s_addr,
+ hp->h_addr,
+ hp->h_length);
+ return this->set (port_number,
+ encode ? ntohl (addrv4.s_addr) : addrv4.s_addr,
+ encode);
+ }
+ }
+#endif /* ACE_HAS_IPV6 */
+}
+
+
+// Initializes a ACE_INET_Addr from a <port_name> and the remote
+// <host_name>.
+
+int
+ACE_INET_Addr::set (const char port_name[],
+ const char host_name[],
+ const char protocol[])
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+
+#if defined (VXWORKS) || defined (CHORUS) || defined (ACE_LACKS_GETSERVBYNAME)
+ ACE_UNUSED_ARG (port_name);
+ ACE_UNUSED_ARG (host_name);
+ ACE_UNUSED_ARG (protocol);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ servent sentry;
+ ACE_SERVENT_DATA buf;
+
+ servent *sp = ACE_OS::getservbyname_r (port_name,
+ protocol,
+ &sentry,
+ buf);
+ if (sp == 0)
+ return -1;
+
+ int address_family = PF_UNSPEC;
+# if defined (ACE_HAS_IPV6)
+ if (ACE_OS_String::strcmp (protocol, ACE_LIB_TEXT ("tcp6")) == 0)
+ address_family = AF_INET6;
+# endif /* ACE_HAS_IPV6 */
+
+ return this->set (sp->s_port, host_name, 0, address_family);
+#endif /* VXWORKS */
+}
+
+// Initializes a ACE_INET_Addr from a <port_name> and a 32 bit Internet
+// address.
+
+int
+ACE_INET_Addr::set (const char port_name[],
+ ACE_UINT32 inet_address,
+ const char protocol[])
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+
+#if defined (VXWORKS) || defined (CHORUS) || defined (ACE_LACKS_GETSERVBYNAME)
+ ACE_UNUSED_ARG (port_name);
+ ACE_UNUSED_ARG (inet_address);
+ ACE_UNUSED_ARG (protocol);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ servent sentry;
+ ACE_SERVENT_DATA buf;
+
+ servent *sp = ACE_OS::getservbyname_r (port_name,
+ protocol,
+ &sentry,
+ buf);
+ if (sp == 0)
+ return -1;
+ else
+ return this->set (sp->s_port, inet_address, 0);
+#endif /* VXWORKS */
+}
+
+// Creates a ACE_INET_Addr from a PORT_NUMBER and the remote
+// HOST_NAME.
+
+
+ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
+ const char host_name[],
+ int address_family)
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_number,
+ host_name,
+ 1,
+ address_family) == -1)
+#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS)
+ ACE_ERROR ((LM_ERROR,
+ (char *)"ACE_INET_Addr::ACE_INET_Addr: %p\n",
+ (((char *) host_name == 0) ?
+ ((char *) "<unknown>") :
+ ((char *) (host_name)))));
+#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
+ ACE_TEXT_CHAR_TO_TCHAR ((host_name == 0) ?
+ "<unknown>" : host_name)));
+#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
+ const wchar_t host_name[],
+ int address_family)
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_number,
+ host_name,
+ 1,
+ address_family) == -1)
+#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS)
+ ACE_ERROR ((LM_ERROR,
+ (char *)"ACE_INET_Addr::ACE_INET_Addr: %p\n",
+ (((char *) host_name == 0) ?
+ ((char *) "<unknown>") :
+ ((char *) (host_name)))));
+#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
+ ACE_TEXT_WCHAR_TO_TCHAR ((host_name == 0) ?
+ ACE_TEXT_WIDE ("<unknown>") :
+ host_name)));
+#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+}
+#endif /* ACE_HAS_WCHAR */
+
+// Creates a ACE_INET_Addr from a sockaddr_in structure.
+
+int
+ACE_INET_Addr::set (const sockaddr_in *addr, int len)
+{
+ ACE_TRACE ("ACE_INET_Addr::set");
+
+ if (addr->sin_family == AF_INET)
+ {
+ ACE_OS::memcpy (&this->inet_addr_.in4_, addr, len);
+ this->base_set (AF_INET, len);
+ return 0;
+ }
+#if defined (ACE_HAS_IPV6)
+ else if (addr->sin_family == AF_INET6)
+ {
+ ACE_OS::memcpy (&this->inet_addr_.in6_, addr, len);
+ this->base_set (AF_INET6, len);
+ return 0;
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+// Set a pointer to the address.
+void
+ACE_INET_Addr::set_addr (void *addr, int len)
+{
+ ACE_TRACE ("ACE_INET_Addr::set_addr");
+ ACE_UNUSED_ARG (len);
+
+ struct sockaddr_in *getfamily = ACE_static_cast (struct sockaddr_in *, addr);
+
+ if (getfamily->sin_family == AF_INET)
+ {
+ this->set_address (ACE_reinterpret_cast (const char*, &getfamily->sin_addr),
+ sizeof (getfamily->sin_addr),
+ 0);
+ }
+#if defined ACE_HAS_IPV6
+ else if (getfamily->sin_family == AF_INET6)
+ {
+ struct sockaddr_in6 *in6 = ACE_static_cast (struct sockaddr_in6*, addr);
+ this->set_address (ACE_reinterpret_cast (const char*, &in6->sin6_addr),
+ sizeof (in6->sin6_addr),
+ 0);
+ }
+#endif // ACE_HAS_IPV6
+}
+
+// Creates a ACE_INET_Addr from a sockaddr_in structure.
+
+
+ACE_INET_Addr::ACE_INET_Addr (const sockaddr_in *addr, int len)
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ this->set (addr, len);
+}
+
+// Creates a ACE_INET_Addr from a PORT_NUMBER and an Internet address.
+
+
+ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
+ ACE_UINT32 inet_address)
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_number, inet_address) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+}
+
+// Creates a ACE_INET_Addr from a PORT_NAME and the remote
+// HOST_NAME.
+
+ACE_INET_Addr::ACE_INET_Addr (const char port_name[],
+ const char host_name[],
+ const char protocol[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_name,
+ host_name,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[],
+ const wchar_t host_name[],
+ const wchar_t protocol[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_name,
+ host_name,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+}
+#endif /* ACE_HAS_WCHAR */
+
+// Creates a ACE_INET_Addr from a PORT_NAME and an Internet address.
+
+
+ACE_INET_Addr::ACE_INET_Addr (const char port_name[],
+ ACE_UINT32 inet_address,
+ const char protocol[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_name,
+ inet_address,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[],
+ ACE_UINT32 inet_address,
+ const wchar_t protocol[])
+ : ACE_Addr (this->determine_type(), sizeof (inet_addr_))
+{
+ ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
+ ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
+ if (this->set (port_name,
+ inet_address,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
+}
+#endif /* ACE_HAS_WCHAR */
+
+int
+ACE_INET_Addr::get_host_name (char hostname[],
+ size_t len) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_host_name");
+
+ int result;
+ if (len > 1)
+ {
+ result = get_host_name_i(hostname,len);
+ if (result < 0)
+ {
+ if (result == -2)
+ {
+ result = -1;
+ // We know that hostname is nul-terminated
+ }
+ else
+ {
+ //result == -1;
+ // This could be worse than hostname[len -1] = '\0'?
+ hostname[0] = '\0';
+ }
+ }
+ }
+ else
+ {
+ if (len == 1)
+ {
+ hostname[0] = '\0';
+ }
+ result = -1;
+ }
+
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+int
+ACE_INET_Addr::get_host_name (wchar_t hostname[],
+ size_t len) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_host_name");
+
+ char char_hostname [MAXHOSTNAMELEN + 1];
+
+ // We have a build in limitation of MAXHOSTNAMELEN
+ if (len > MAXHOSTNAMELEN + 1)
+ len = MAXHOSTNAMELEN + 1;
+
+ // Call the char version
+ int result = this->get_host_name (char_hostname, len);
+
+ // And copy it over, if successful
+ if (result == 0)
+ ACE_OS_String::strcpy (hostname,
+ ACE_Ascii_To_Wide (char_hostname).wchar_rep ());
+
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+// Return the character representation of the hostname.
+
+const char *
+ACE_INET_Addr::get_host_name (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_host_name");
+
+ static char name[MAXHOSTNAMELEN + 1];
+ if (this->get_host_name (name, MAXHOSTNAMELEN + 1) == -1)
+ ACE_OS::strcpy (name, "<unknown>");
+ return name;
+}
+
+void
+ACE_INET_Addr::set_port_number (u_short port_number,
+ int encode)
+{
+ ACE_TRACE ("ACE_INET_Addr::set_port_number");
+
+ if (encode)
+ port_number = htons (port_number);
+
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ this->inet_addr_.in6_.sin6_port = port_number;
+ else
+#endif /* ACE_HAS_IPV6 */
+ this->inet_addr_.in4_.sin_port = port_number;
+}
+
+// returns -2 when the hostname is truncated
+int
+ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_host_name_i");
+
+#if defined (ACE_HAS_IPV6)
+ if ((this->get_type () == PF_INET6 &&
+ 0 == ACE_OS_String::memcmp (&this->inet_addr_.in6_.sin6_addr,
+ &in6addr_any,
+ sizeof (this->inet_addr_.in6_.sin6_addr)))
+ ||
+ (this->get_type () == PF_INET &&
+ this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY))
+#else
+ if (this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY)
+#endif /* ACE_HAS_IPV6 */
+ {
+ if (ACE_OS::hostname (hostname, len) == -1)
+ return -1;
+ else
+ return 0;
+ }
+ else
+ {
+#if defined (VXWORKS)
+ ACE_UNUSED_ARG (len);
+ int error =
+ ::hostGetByAddr ((int) this->inet_addr_.in4_.sin_addr.s_addr,
+ hostname);
+ if (error == OK)
+ return 0;
+ else
+ {
+ errno = error;
+ return -1;
+ }
+#else
+ int error = 0;
+
+# if defined (CHORUS) || (defined (DIGITAL_UNIX) && defined (__GNUC__))
+ hostent *hp = ACE_OS::gethostbyaddr ((char *)this->ip_addr_pointer (),
+ this->ip_addr_size (),
+ this->get_type ());
+ if (hp == 0)
+ error = errno; // So that the errno gets propagated back; it is
+ // loaded from error below.
+# else
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+ hostent *hp =
+ ACE_OS::gethostbyaddr_r ((char *)this->ip_addr_pointer (),
+ this->ip_addr_size (),
+ this->get_type (),
+ &hentry,
+ buf,
+ &error);
+# endif /* CHORUS */
+
+ if (hp == 0)
+ {
+ errno = error;
+ return -1;
+ }
+
+ if (hp->h_name == 0)
+ return -1;
+
+ if (ACE_OS::strlen (hp->h_name) >= len)
+ {
+ // We know the length, so use memcpy
+ if (len > 0)
+ {
+ ACE_OS::memcpy (hostname, hp->h_name, len - 1);
+ hostname[len-1]= '\0';
+ }
+ errno = ENOSPC;
+ return -2; // -2 Means that we have a good string
+ // Using errno looks ok, but ENOSPC could be set on
+ // other places.
+ }
+
+ ACE_OS::strcpy (hostname, hp->h_name);
+ return 0;
+#endif /* VXWORKS */
+ }
+}
+
+int ACE_INET_Addr::set_address (const char *ip_addr,
+ int len,
+ int encode /* = 1 */)
+{
+ ACE_TRACE ("ACE_INET_Addr::set_address");
+ // This is really intended for IPv4. If the object is IPv4, or the type
+ // hasn't been set but it's a 4-byte address, go ahead. If this is an
+ // IPv6 object and <encode> is requested, refuse.
+ if (encode && len != 4)
+ {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (len == 4)
+ {
+ ACE_UINT32 ip4 = *ACE_reinterpret_cast (const ACE_UINT32 *, ip_addr);
+ if (encode)
+ ip4 = ACE_HTONL (ip4);
+
+
+ if (this->get_type () == AF_INET) {
+ this->base_set (AF_INET, sizeof (this->inet_addr_.in4_));
+ this->inet_addr_.in4_.sin_family = AF_INET;
+ this->set_size (sizeof (this->inet_addr_.in4_));
+ ACE_OS_String::memcpy (&this->inet_addr_.in4_.sin_addr,
+ &ip4,
+ len);
+ }
+#if defined (ACE_HAS_IPV6)
+ // If given an IPv4 address to copy to an IPv6 object, map it to
+ // an IPv4-mapped IPv6 address.
+ else
+ {
+ this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_));
+ this->inet_addr_.in6_.sin6_family = AF_INET6;
+ this->set_size (sizeof (this->inet_addr_.in6_));
+ if (ip4 == INADDR_ANY)
+ {
+ in6_addr ip6 = in6addr_any;
+ ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr,
+ &ip6,
+ sizeof (ip6));
+ return 0;
+ }
+ if (ip4 == INADDR_LOOPBACK)
+ {
+ in6_addr ip6 = in6addr_loopback;
+ ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr,
+ &ip6,
+ sizeof (ip6));
+ return 0;
+ }
+
+ // Build up a 128 bit address. An IPv4-mapped IPv6 address
+ // is defined as 0:0:0:0:0:ffff:IPv4_address. This is defined
+ // in RFC 1884 */
+ struct {
+ ACE_UINT16 prefix[5];
+ ACE_UINT16 ffff;
+ ACE_UINT32 addr;
+ } newaddress = {
+ { 0,0,0,0,0 },
+ 0xffff,
+ ip4
+ };
+
+ ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr,
+ &newaddress,
+ sizeof (newaddress));
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ return 0;
+ } /* end if (len == 4) */
+#if defined (ACE_HAS_IPV6)
+ else if (len == 16)
+ {
+ if (this->get_type () != PF_INET6)
+ {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ // We protect ourselves up above so IPv6 must be possible here.
+ this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_));
+ this->inet_addr_.in6_.sin6_family = AF_INET6;
+ ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr, ip_addr, len);
+
+ return 0;
+ } /* end len == 16 */
+ else
+ {
+ /* unknown or unsupported address length */
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+#endif /* ACE_HAS_IPV6 */
+
+ // Here with an unrecognized length.
+ errno = EAFNOSUPPORT;
+ return -1;
+
+}
+
+
+const char *
+ACE_INET_Addr::get_host_addr (char *dst, int size) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ {
+ if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr))
+ {
+ ACE_UINT32 addr;
+ addr = this->get_ip_address();
+ addr = ACE_HTONL (addr);
+ return ACE_OS::inet_ntop (AF_INET, &addr, dst, size);
+ }
+
+ const char *ch = ACE_OS::inet_ntop (AF_INET6,
+ &this->inet_addr_.in6_.sin6_addr,
+ dst,
+ size);
+ return ch;
+ }
+#endif /* ACE_HAS_IPV6 */
+
+#if defined (VXWORKS)
+ // It would be nice to be able to encapsulate this into
+ // ACE_OS::inet_ntoa(), but that would lead to either inefficiencies
+ // on vxworks or lack of thread safety.
+ //
+ // So, we use the way that vxworks suggests.
+ ACE_INET_Addr *ncthis = ACE_const_cast (ACE_INET_Addr *, this);
+ inet_ntoa_b (this->inet_addr_.in4_.sin_addr, ncthis->buf_);
+ return &buf_[0];
+#else /* VXWORKS */
+ char *ch = ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr);
+ ACE_OS::strncpy (dst, ch, size);
+ return ch;
+#endif
+}
+
+// Return the dotted Internet address.
+const char *
+ACE_INET_Addr::get_host_addr (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_host_addr");
+#if defined (ACE_HAS_IPV6)
+ static char buf[INET6_ADDRSTRLEN];
+ return this->get_host_addr (buf, INET6_ADDRSTRLEN);
+#else
+ return ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr);
+#endif
+}
+
+// Return the 4-byte IP address, converting it into host byte order.
+
+ACE_UINT32
+ACE_INET_Addr::get_ip_address (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_ip_address");
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == AF_INET6)
+ {
+ if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr) ||
+ IN6_IS_ADDR_V4COMPAT (&this->inet_addr_.in6_.sin6_addr) )
+ {
+ ACE_UINT32 addr;
+ // Return the last 32 bits of the address
+ char *thisaddrptr = (char*)this->ip_addr_pointer ();
+ thisaddrptr += 128/8 - 32/8;
+ ACE_OS_String::memcpy (&addr, thisaddrptr, sizeof (addr));
+ return ACE_NTOHL (addr);
+ }
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4\n")));
+ errno = EAFNOSUPPORT;
+ return 0;
+ }
+#endif /* ACE_HAS_IPV6 */
+ return ntohl (ACE_UINT32 (this->inet_addr_.in4_.sin_addr.s_addr));
+}
diff --git a/ace/IPC/INET_Addr.h b/ace/IPC/INET_Addr.h
new file mode 100644
index 00000000000..3cee7b8ac94
--- /dev/null
+++ b/ace/IPC/INET_Addr.h
@@ -0,0 +1,330 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file INET_Addr.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_INET_ADDR_H
+#define ACE_INET_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+
+#if defined(VXWORKS)
+# include /**/ "inetLib.h"
+#endif /* VXWORKS */
+
+/**
+ * @class ACE_INET_Addr
+ *
+ * @brief Defines a C++ wrapper facade for the Internet domain address
+ * family format.
+ */
+class ACE_Export ACE_INET_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+
+ /// Default constructor.
+ ACE_INET_Addr (void);
+
+ /// Copy constructor.
+ ACE_INET_Addr (const ACE_INET_Addr &);
+
+ /// Creates an <ACE_INET_Addr> from a sockaddr_in structure.
+ ACE_INET_Addr (const sockaddr_in *, int len);
+
+ /// Creates an <ACE_INET_Addr> from a <port_number> and the remote
+ /// <host_name>. The port number is assumed to be in host byte order.
+ /// To set a port already in network byte order, please @see set().
+ /// Use address_family to select IPv6 (PF_INET6) vs. IPv4 (PF_INET).
+ ACE_INET_Addr (u_short port_number,
+ const char host_name[],
+ int address_family = AF_UNSPEC);
+
+ /**
+ * Initializes an <ACE_INET_Addr> from the <address>, which can be
+ * "ip-number:port-number" (e.g., "tango.cs.wustl.edu:1234" or
+ * "128.252.166.57:1234"). If there is no ':' in the <address> it
+ * is assumed to be a port number, with the IP address being
+ * INADDR_ANY.
+ */
+ ACE_EXPLICIT ACE_INET_Addr (const char address[]);
+
+ /**
+ * Creates an <ACE_INET_Addr> from a <port_number> and an Internet
+ * <ip_addr>. This method assumes that <port_number> and <ip_addr>
+ * are in host byte order. If you have addressing information in
+ * network byte order, @see set().
+ */
+ ACE_INET_Addr (u_short port_number,
+ ACE_UINT32 ip_addr = INADDR_ANY);
+
+ /// Uses <getservbyname> to create an <ACE_INET_Addr> from a
+ /// <port_name>, the remote <host_name>, and the <protocol>.
+ ACE_INET_Addr (const char port_name[],
+ const char host_name[],
+ const char protocol[] = "tcp");
+
+ /**
+ * Uses <getservbyname> to create an <ACE_INET_Addr> from a
+ * <port_name>, an Internet <ip_addr>, and the <protocol>. This
+ * method assumes that <ip_addr> is in host byte order.
+ */
+ ACE_INET_Addr (const char port_name[],
+ ACE_UINT32 ip_addr,
+ const char protocol[] = "tcp");
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_INET_Addr (u_short port_number,
+ const wchar_t host_name[],
+ int address_family = AF_UNSPEC);
+
+ ACE_EXPLICIT ACE_INET_Addr (const wchar_t address[]);
+
+ ACE_INET_Addr (const wchar_t port_name[],
+ const wchar_t host_name[],
+ const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp"));
+
+ ACE_INET_Addr (const wchar_t port_name[],
+ ACE_UINT32 ip_addr,
+ const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp"));
+#endif /* ACE_HAS_WCHAR */
+
+ /// Default dtor.
+ ~ACE_INET_Addr (void);
+
+ // = Direct initialization methods.
+
+ // These methods are useful after the object has been constructed.
+
+ /// Initializes from another <ACE_INET_Addr>.
+ int set (const ACE_INET_Addr &);
+
+ /**
+ * Initializes an <ACE_INET_Addr> from a <port_number> and the
+ * remote <host_name>. If <encode> is non-zero then <port_number> is
+ * converted into network byte order, otherwise it is assumed to be
+ * in network byte order already and are passed straight through.
+ * address_family can be used to select IPv4/IPv6 if the OS has
+ * IPv6 capability (ACE_HAS_IPV6 is defined). To specify IPv6, use
+ * the value AF_INET6. To specify IPv4, use AF_INET.
+ */
+ int set (u_short port_number,
+ const char host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC);
+
+ /**
+ * Initializes an <ACE_INET_Addr> from a @param port_number and an
+ * Internet @param ip_addr. If @param encode is non-zero then the
+ * port number and IP address are converted into network byte order,
+ * otherwise they are assumed to be in network byte order already and
+ * are passed straight through.
+ */
+ int set (u_short port_number,
+ ACE_UINT32 ip_addr = INADDR_ANY,
+ int encode = 1);
+
+ /// Uses <getservbyname> to initialize an <ACE_INET_Addr> from a
+ /// <port_name>, the remote <host_name>, and the <protocol>.
+ int set (const char port_name[],
+ const char host_name[],
+ const char protocol[] = "tcp");
+
+ /**
+ * Uses <getservbyname> to initialize an <ACE_INET_Addr> from a
+ * <port_name>, an <ip_addr>, and the <protocol>. This assumes that
+ * <ip_addr> is already in network byte order.
+ */
+ int set (const char port_name[],
+ ACE_UINT32 ip_addr,
+ const char protocol[] = "tcp");
+
+ /**
+ * Initializes an <ACE_INET_Addr> from the <addr>, which can be
+ * "ip-number:port-number" (e.g., "tango.cs.wustl.edu:1234" or
+ * "128.252.166.57:1234"). If there is no ':' in the <address> it
+ * is assumed to be a port number, with the IP address being
+ * INADDR_ANY.
+ */
+ int set (const char addr[]);
+
+ /// Creates an <ACE_INET_Addr> from a sockaddr_in structure.
+ int set (const sockaddr_in *,
+ int len);
+
+#if defined (ACE_HAS_WCHAR)
+ int set (u_short port_number,
+ const wchar_t host_name[],
+ int encode = 1,
+ int address_family = AF_UNSPEC);
+
+ int set (const wchar_t port_name[],
+ const wchar_t host_name[],
+ const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp"));
+
+ int set (const wchar_t port_name[],
+ ACE_UINT32 ip_addr,
+ const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp"));
+
+ int set (const wchar_t addr[]);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Return a pointer to the underlying network address.
+ virtual void *get_addr (void) const;
+ int get_addr_size(void) const;
+
+ /// Set a pointer to the address.
+ virtual void set_addr (void *, int len);
+
+ /**
+ * Transform the current <ACE_INET_Addr> address into string format.
+ * If <ipaddr_format> is non-0 this produces "ip-number:port-number"
+ * (e.g., "128.252.166.57:1234"), whereas if <ipaddr_format> is 0
+ * this produces "ip-name:port-number" (e.g.,
+ * "tango.cs.wustl.edu:1234"). Returns -1 if the <size> of the
+ * <buffer> is too small, else 0.
+ */
+ virtual int addr_to_string (ACE_TCHAR buffer[],
+ size_t size,
+ int ipaddr_format = 1) const;
+
+ /**
+ * Initializes an <ACE_INET_Addr> from the <address>, which can be
+ * "ip-addr:port-number" (e.g., "tango.cs.wustl.edu:1234"),
+ * "ip-addr:port-name" (e.g., "tango.cs.wustl.edu:telnet"),
+ * "ip-number:port-number" (e.g., "128.252.166.57:1234"), or
+ * "ip-number:port-name" (e.g., "128.252.166.57:telnet"). If there
+ * is no ':' in the <address> it is assumed to be a port number,
+ * with the IP address being INADDR_ANY.
+ */
+ virtual int string_to_addr (const char address[]);
+
+#if defined (ACE_HAS_WCHAR)
+ /*
+ virtual int string_to_addr (const char address[]);
+ */
+#endif /* ACE_HAS_WCHAR */
+
+ /**
+ * Sets the port number without affecting the host name. If
+ * <encode> is enabled then <port_number> is converted into network
+ * byte order, otherwise it is assumed to be in network byte order
+ * already and are passed straight through.
+ */
+ void set_port_number (u_short,
+ int encode = 1);
+
+ /**
+ * Sets the address without affecting the port number. If
+ * <encode> is enabled then <ip_addr> is converted into network
+ * byte order, otherwise it is assumed to be in network byte order
+ * already and are passed straight through. The size of the address
+ * is specified in the <len> parameter.
+ */
+ int set_address (const char *ip_addr,
+ int len,
+ int encode = 1);
+
+ /// Return the port number, converting it into host byte-order.
+ u_short get_port_number (void) const;
+
+ /**
+ * Return the character representation of the name of the host,
+ * storing it in the <hostname> (which is assumed to be
+ * <hostnamelen> bytes long). This version is reentrant. If
+ * <hostnamelen> is greater than 0 then <hostname> will be
+ * NUL-terminated even if -1 is returned.
+ */
+ int get_host_name (char hostname[],
+ size_t hostnamelen) const;
+
+#if defined (ACE_HAS_WCHAR)
+ int get_host_name (wchar_t hostname[],
+ size_t hostnamelen) const;
+#endif /* ACE_HAS_WCHAR */
+
+ /**
+ * Return the character representation of the hostname (this version
+ * is non-reentrant since it returns a pointer to a static data
+ * area).
+ */
+ const char *get_host_name (void) const;
+
+ /// Return the "dotted decimal" Internet address.
+ const char *get_host_addr (void) const;
+ const char *get_host_addr (char *dst, int size) const;
+
+ /// Return the 4-byte IP address, converting it into host byte
+ /// order.
+ ACE_UINT32 get_ip_address (void) const;
+
+ /**
+ * Returns true if <this> is less than <rhs>. In this context,
+ * "less than" is defined in terms of IP address and TCP port
+ * number. This operator makes it possible to use <ACE_INET_Addr>s
+ * in STL maps.
+ */
+ int operator < (const ACE_INET_Addr &rhs) const;
+
+ /// Compare two addresses for equality. The addresses are considered
+ /// equal if they contain the same IP address and port number.
+ int operator == (const ACE_INET_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ int operator != (const ACE_INET_Addr &SAP) const;
+
+ /// Computes and returns hash value.
+ virtual u_long hash (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Insure that @arg hostname is properly null-terminated.
+ int get_host_name_i (char hostname[], size_t hostnamelen) const;
+
+ // Methods to gain access to the actual address of
+ // the underlying internet address structure.
+ void *ip_addr_pointer (void) const;
+ size_t ip_addr_size (void) const;
+ int determine_type (void) const;
+
+ /// Underlying representation.
+ /// This union uses the knowledge that the two structures share the
+ /// first member, sa_family (as all sockaddr structures do).
+ union
+ {
+ sockaddr_in in4_;
+#if defined (ACE_HAS_IPV6)
+ sockaddr_in6 in6_;
+#endif /* ACE_HAS_IPV6 */
+ } inet_addr_;
+
+#if defined (VXWORKS)
+ char buf_[INET_ADDR_LEN];
+#endif
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/INET_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_INET_ADDR_H */
diff --git a/ace/IPC/INET_Addr.i b/ace/IPC/INET_Addr.i
new file mode 100644
index 00000000000..44e74f0f88f
--- /dev/null
+++ b/ace/IPC/INET_Addr.i
@@ -0,0 +1,159 @@
+/* -*- C++ -*- */
+// $Id$
+
+// INET_Addr.i
+
+// Default dtor.
+ACE_INLINE
+ACE_INET_Addr::~ACE_INET_Addr (void)
+{
+}
+
+ACE_INLINE int
+ACE_INET_Addr::determine_type (void) const
+{
+#if defined (ACE_HAS_IPV6)
+# if defined (ACE_USES_IPV4_IPV6_MIGRATION)
+ return ACE_Sock_Connect::ipv6_enabled () ? AF_INET6 : AF_INET;
+# else
+ return AF_INET6;
+# endif /* ACE_USES_IPV4_IPV6_MIGRATION */
+#endif /* ACE_HAS_IPV6 */
+ return AF_INET;
+}
+
+ACE_INLINE void *
+ACE_INET_Addr::ip_addr_pointer (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET)
+ return (void*)&this->inet_addr_.in4_.sin_addr;
+ else
+ return (void*)&this->inet_addr_.in6_.sin6_addr;
+#else
+ return (void*)&this->inet_addr_.in4_.sin_addr;
+#endif
+}
+
+ACE_INLINE size_t
+ACE_INET_Addr::ip_addr_size (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET)
+ return sizeof this->inet_addr_.in4_.sin_addr;
+ else
+ return sizeof this->inet_addr_.in6_.sin6_addr;
+#else
+ // These _UNICOS changes were picked up from pre-IPv6 code in
+ // get_host_name_i... the IPv6 section above may need something
+ // similar, so keep an eye out for it.
+# if !defined(_UNICOS)
+ return sizeof this->inet_addr_.in4_.sin_addr.s_addr;
+# else /* _UNICOS */
+ return sizeof this->inet_addr_.in4_.sin_addr;
+# endif /* ! _UNICOS */
+#endif /* ACE_HAS_IPV6 */
+}
+
+// Return the port number, converting it into host byte order...
+
+ACE_INLINE u_short
+ACE_INET_Addr::get_port_number (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_port_number");
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET)
+ return ntohs (this->inet_addr_.in4_.sin_port);
+ else
+ return ntohs (this->inet_addr_.in6_.sin6_port);
+#else
+ return ntohs (this->inet_addr_.in4_.sin_port);
+#endif /* ACE_HAS_IPV6 */
+}
+
+// Return the address.
+
+ACE_INLINE void *
+ACE_INET_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_addr");
+ return (void*)&this->inet_addr_;
+}
+
+ACE_INLINE int
+ACE_INET_Addr::get_addr_size (void) const
+{
+ ACE_TRACE ("ACE_INET_Addr::get_addr_size");
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET)
+ return sizeof this->inet_addr_.in4_;
+ else
+ return sizeof this->inet_addr_.in6_;
+#else
+ return sizeof this->inet_addr_.in4_;
+#endif /* ACE_HAS_IPV6 */
+}
+
+
+ACE_INLINE u_long
+ACE_INET_Addr::hash (void) const
+{
+#if defined (ACE_HAS_IPV6)
+ if (this->get_type () == PF_INET6)
+ {
+ const unsigned int *addr = (const unsigned int*)this->ip_addr_pointer();
+ return addr[0] + addr[1] + addr[2] + addr[3] + this->get_port_number();
+ }
+ else
+#endif /* ACE_HAS_IPV6 */
+ return this->get_ip_address () + this->get_port_number ();
+}
+
+ACE_INLINE int
+ACE_INET_Addr::operator < (const ACE_INET_Addr &rhs) const
+{
+ return this->get_ip_address () < rhs.get_ip_address ()
+ || (this->get_ip_address () == rhs.get_ip_address ()
+ && this->get_port_number () < rhs.get_port_number ());
+}
+
+#if defined (ACE_HAS_WCHAR)
+ACE_INLINE int
+ACE_INET_Addr::set (u_short port_number,
+ const wchar_t host_name[],
+ int encode,
+ int address_family)
+{
+ return this->set (port_number,
+ ACE_Wide_To_Ascii (host_name).char_rep (),
+ encode,
+ address_family);
+}
+
+ACE_INLINE int
+ACE_INET_Addr::set (const wchar_t port_name[],
+ const wchar_t host_name[],
+ const wchar_t protocol[])
+{
+ return this->set (ACE_Wide_To_Ascii (port_name).char_rep (),
+ ACE_Wide_To_Ascii (host_name).char_rep (),
+ ACE_Wide_To_Ascii (protocol).char_rep ());
+}
+
+ACE_INLINE int
+ACE_INET_Addr::set (const wchar_t port_name[],
+ ACE_UINT32 ip_addr,
+ const wchar_t protocol[])
+{
+ return this->set (ACE_Wide_To_Ascii (port_name).char_rep (),
+ ip_addr,
+ ACE_Wide_To_Ascii (protocol).char_rep ());
+}
+
+ACE_INLINE int
+ACE_INET_Addr::set (const wchar_t addr[])
+{
+ return this->set (ACE_Wide_To_Ascii (addr).char_rep ());
+}
+
+#endif /* ACE_HAS_WCHAR */
diff --git a/ace/IPC/IOStream.cpp b/ace/IPC/IOStream.cpp
new file mode 100644
index 00000000000..c024f85537f
--- /dev/null
+++ b/ace/IPC/IOStream.cpp
@@ -0,0 +1,658 @@
+// $Id$
+
+#if !defined (ACE_IOSTREAM_C)
+#define ACE_IOSTREAM_C
+
+#include "ace/IOStream.h"
+
+ACE_RCSID(ace, IOStream, "$Id$")
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+///////////////////////////////////////////////////////////////////////////
+
+/* Here's a simple example of how iostream's non-virtual operators can
+ get you in a mess:
+
+ class myiostream : public iostream
+ {
+ public:
+ myiostream& operator>> (String & s)
+ {
+ ...
+ }
+ };
+
+ ...
+
+ int i;
+ String s;
+ myiostream foo (...);
+
+ foo >> s;
+ // OK
+ // invokes myiostream::operator>> (String&) returning myiostream&
+
+ foo >> i;
+ // OK
+ // invokes iostream::operator>> (int&) returning iostream&
+
+ foo >> i >> s;
+ // BAD
+ // invokes iostream::operator>> (int&) then iostream::operator>> (String&)
+ //
+ // What has happened is that the first >> is invoked on the base class and returns
+ // a reference to iostream. The second >> has no idea of the ACE_IOStream and
+ // gets invoked on iostream. Probably NOT what you wanted!
+
+
+ // In order to make all of this work the way you want, you have to do this:
+
+ class myiostream : public iostream
+ {
+ public:
+ myiostream& operator>> (int & i)
+ {
+ return ((myiostream&)iostream::operator>> (i));
+ }
+
+ myiostream& operator>> (String & s)
+ {
+ ...
+ }
+ };
+
+ ...
+
+ int i;
+ String s;
+ myiostream foo (...);
+
+ foo >> s;
+ // OK
+ // invokes myiostream::operator>> (String&) returning myiostream&
+
+ foo >> i;
+ // OK
+ // invokes myiostream::operator>> (int&) returning myiostream&
+
+
+ foo >> i >> s;
+ // OK
+ // Because you provided operator>> (int&) in class myiostream, that
+ // function will be invoked by the first >>. Since it returns
+ // a myiostream&, the second >> will be invoked as desired. */
+
+ACE_HANDLE
+ACE_Streambuf::get_handle (void)
+{
+ return 0;
+}
+
+ACE_Time_Value *
+ACE_Streambuf::recv_timeout (ACE_Time_Value *tv)
+{
+ ACE_Time_Value * rval = recv_timeout_;
+ if (tv)
+ {
+ recv_timeout_value_ = *tv;
+ recv_timeout_ = &recv_timeout_value_;
+ }
+ else
+ recv_timeout_ = NULL;
+
+ return rval;
+}
+
+int
+ACE_Streambuf::underflow (void)
+{
+ // If input mode is not set, any attempt to read from the stream is
+ // a failure.
+
+ if (ACE_BIT_DISABLED (mode_, ios::in))
+ return EOF;
+
+ // If base () is empty then this is the first time any get/put
+ // operation has been attempted on the stream.
+
+ if (!this->base ())
+ {
+ // Set base () to use our private read buffer. The arguments are:
+ // beginning of the buffer (base ())
+ // one-beyond the end of the buffer (ebase ())
+ // should base () be deleted on destruction
+ //
+ // We have to say "no" to the third parameter because we want to
+ // explicitly handle deletion of the TWO buffers at destruction.
+
+ setb (this->eback_saved_,
+ this->eback_saved_ + streambuf_size_, 0);
+
+ // Remember that we are now in getMode. This will help us if
+ // we're called prior to a mode change as well as helping us
+ // when the mode does change.
+ this->cur_mode_ = this->get_mode_;
+ // Using the new values for base (), initialize the get area.
+ // This simply sets eback (), gptr () and egptr () described
+ // earlier.
+ setg (base (), base (), base ());
+
+ // Set the put buffer such that puts will be disabled. Any
+ // attempt to put data will now cause overflow to be invoked.
+ setp (0, 0);
+ }
+ else // base () has been initialized already...
+ {
+ // If we are in put_mode_ now, then it is time to switch to get_mode_
+ //
+ // 1. get rid of any pending output
+ // 2. rearrange base () to use our half of the buffer
+ // 3. reset the mode
+ //
+ if (this->cur_mode_ == this->put_mode_)
+ {
+ // Dump any pending output to the peer. This is not really
+ // necessary because of the dual-buffer arrangement we've
+ // set up but intuitively it makes sense to send the pending
+ // data before we request data since the peer will probably
+ // need what we're sending before it can respond.
+ if (out_waiting () && syncout () == EOF)
+ return EOF;
+
+ if( ! pbase() )
+ {
+ delete [] pbase_saved_;
+ (void) reset_put_buffer();
+ }
+ else
+ {
+ // We're about to disable put mode but before we do
+ // that, we want to preserve it's state.
+ this->pbase_saved_ = pbase ();
+ this->pptr_saved_ = pptr ();
+ this->epptr_saved_ = epptr ();
+ }
+
+ // Disable put mode as described in the constructor.
+ setp (0, 0);
+
+ // Like the case where base () is false, we now point base
+ // () to use our private get buffer.
+ setb (this->eback_saved_,
+ this->eback_saved_ + streambuf_size_,
+ 0);
+
+ // And restore the previous state of the get pointers.
+
+ setg (this->eback_saved_, this->gptr_saved_,
+ this->egptr_saved_);
+
+ // Finally, set our mode so that we don't get back into this
+ // if () and so that overflow can operate correctly.
+ cur_mode_ = get_mode_;
+ }
+
+ // There could be data in the input buffer if we switched to put
+ // mode before reading everything. In that case, we take this
+ // opportunity to feed it back to the iostream.
+ if (in_avail ())
+ // Remember that we return an int so that we can give back
+ // EOF. The explicit cast prevents us from returning a signed
+ // char when we're not returning EOF.
+ return (u_char) *gptr ();
+ }
+
+ // We really shouldn't be here unless there is a lack of data in the
+ // read buffer. So... go get some more data from the peer.
+
+ int result = fillbuf ();
+
+ // Fillbuf will give us EOF if there was an error with the peer. In
+ // that case, we can do no more input.
+
+ if (EOF == result)
+ {
+ // Disable ourselves and return failure to the iostream. That
+ // should result in a call to have oursleves closed.
+ setg (0, 0, 0);
+ return EOF;
+ }
+
+ // Return the next available character in the input buffer. Again,
+ // we protect against sign extension.
+
+ return (u_char) *gptr ();
+}
+
+// Much of this is similar to underflow. I'll just hit the highlights
+// rather than repeating a lot of what you've already seen.
+
+int
+ACE_Streambuf::overflow (int c)
+{
+ // Check to see if output is allowed at all.
+ if (! (mode_ & ios::out))
+ return EOF;
+
+ if (!base ())
+ {
+ // Set base () to use put's private buffer.
+ //
+ setb (this->pbase_saved_,
+ this->pbase_saved_ + streambuf_size_, 0);
+
+ // Set the mode for optimization.
+ this->cur_mode_ = this->put_mode_;
+ // Set the put area using the new base () values.
+ setp (base (), ebuf ());
+
+ // Disable the get area.
+ setg (0, 0, 0);
+ }
+ else // We're already reading or writing
+ {
+ // If we're coming out of get mode...
+ if (this->cur_mode_ == this->get_mode_)
+ {
+ // --> JCEJ 6/6/98
+ if (! eback())
+ {
+ /* Something has happened to cause the streambuf
+ to get rid of our get area.
+ We could probably do this a bit cleaner but
+ this method is sure to cleanup the bits and
+ pieces.
+ */
+ delete [] eback_saved_;
+ (void) reset_get_buffer();
+ }
+ else
+ {
+ // Save the current get mode values
+ this->eback_saved_ = eback ();
+ this->gptr_saved_ = gptr ();
+ this->egptr_saved_ = egptr ();
+ }
+ // <-- JCEJ 6/6/98
+
+ // then disable the get buffer
+ setg (0, 0, 0);
+
+ // Reconfigure base () and restore the put pointers.
+ setb (pbase_saved_, pbase_saved_ + streambuf_size_, 0);
+ setp (base (), ebuf ());
+
+ // Save the new mode.
+ this->cur_mode_ = this->put_mode_;
+ }
+
+ // If there is output to be flushed, do so now. We shouldn't
+ // get here unless this is the case...
+
+ if (out_waiting () && EOF == syncout ())
+ return EOF;
+ }
+
+ // If we're not putting EOF, then we have to deal with the character
+ // that is being put. Perhaps we should do something special with EOF???
+
+ if (c != EOF)
+ {
+ // We've already written any data that may have been in the
+ // buffer, so we're guaranteed to have room in the buffer for
+ // this new information. So... we add it to the buffer and
+ // adjust our 'next' pointer acordingly.
+ *pptr () = (char) c;
+ pbump (1);
+ }
+
+ return 0;
+}
+
+// syncin
+
+int
+ACE_Streambuf::syncin (void)
+{
+ // As discussed, there really isn't any way to sync input from a
+ // socket-like device. We specifially override this base-class
+ // function so that it won't do anything evil to us.
+ return 0;
+}
+
+// syncout
+
+int
+ACE_Streambuf::syncout (void)
+{
+ // Unlike syncin, syncout is a doable thing. All we have to do is
+ // write whatever is in the output buffer to the peer. flushbuf ()
+ // is how we do it.
+
+ if (flushbuf () == EOF)
+ return EOF;
+ else
+ return 0;
+}
+
+int
+ACE_Streambuf::sync (void)
+{
+ // sync () is fairly traditional in that it syncs both input and
+ // output. We could have omitted the call to syncin () but someday,
+ // we may want it to do something.
+
+ syncin ();
+
+ // Don't bother syncing the output unless there is data to be
+ // sent...
+
+ if (out_waiting ())
+ return syncout ();
+ else
+ return 0;
+}
+
+// flushbuf
+
+int
+ACE_Streambuf::flushbuf (void)
+{
+ // pptr () is one character beyond the last character put into the
+ // buffer. pbase () points to the beginning of the put buffer.
+ // Unless pptr () is greater than pbase () there is nothing to be
+ // sent to the peer.
+
+ if (pptr () <= pbase ())
+ return 0;
+
+ // 4/12/97 -- JCEJ
+ // Kludge!!!
+ // If the remote side shuts down the connection, an attempt to send
+ // () to the remote will result in the message 'Broken Pipe' I think
+ // this is an OS message, I've tracked it down to the ACE_OS::write
+ // () function. That's the last one to be called before the
+ // message. I can only test this on Linux though, so I don't know
+ // how other systems will react.
+ //
+ // To get around this gracefully, I do a PEEK recv () with an
+ // immediate (nearly) timeout. recv () is much more graceful on
+ // it's failure. If we get -1 from recv () not due to timeout then
+ // we know we're SOL.
+ //
+ // Q: Is 'errno' threadsafe? Should the section below be a
+ // critical section?
+ //
+ // char tbuf[1];
+ // ACE_Time_Value to (0,1);
+ // if (this->recv (tbuf, 1, MSG_PEEK, &to) == -1)
+ // {
+ // if (errno != ETIME)
+ // {
+ // perror ("OOPS preparing to send to peer");
+ // return EOF;
+ // }
+ // }
+ //
+ // The correct way to handle this is for the application to trap
+ // (and ignore?) SIGPIPE. Thanks to Amos Shapira for reminding me
+ // of this.
+
+ // Starting at the beginning of the buffer, send as much data as
+ // there is waiting. send guarantees that all of the data will be
+ // sent or an error will be returned.
+
+ if (this->send (pbase (), pptr () - pbase ()) == -1)
+ return EOF;
+
+ // Now that we've sent everything in the output buffer, we reset the
+ // buffer pointers to appear empty.
+ setp (base (), ebuf ());
+
+ return 0;
+}
+
+int
+ACE_Streambuf::get_one_byte (void)
+{
+ this->timeout_ = 0;
+
+ // The recv function will return immediately if there is no data
+ // waiting. So, we use recv_n to wait for exactly one byte to come
+ // from the peer. Later, we can use recv to see if there is
+ // anything else in the buffer. (Ok, we could use flags to tell it
+ // to block but I like this better.)
+
+ if (this->recv_n (base (), 1, MSG_PEEK, this->recv_timeout_) != 1)
+ {
+ if (errno == ETIME)
+ this->timeout_ = 1;
+ return EOF;
+ }
+ else
+ return 1;
+}
+
+// This will be called when the read (get) buffer has been exhausted
+// (ie -- gptr == egptr).
+
+int
+ACE_Streambuf::fillbuf (void)
+{
+ // Invoke recv_n to get exactly one byte from the remote. This will
+ // block until something shows up.
+
+ if (get_one_byte () == EOF)
+ return EOF;
+
+ // Now, get whatever else may be in the buffer. This will return if
+ // there is nothing in the buffer.
+
+ int bc = this->recv (base (), blen (), this->recv_timeout_);
+
+ // recv will give us -1 if there was a problem. If there was
+ // nothing waiting to be read, it will give us 0. That isn't an
+ // error.
+
+ if (bc < 0)
+ {
+ if (errno == ETIME)
+ this->timeout_ = 1;
+ return EOF;
+ }
+
+ // Move the get pointer to reflect the number of bytes we just read.
+
+ setg (base (), base (), base () + bc);
+
+ // Return the byte-read-count including the one from <get_one_byte>.
+ return bc;
+}
+
+ACE_Streambuf::ACE_Streambuf (u_int streambuf_size, int io_mode)
+ : eback_saved_ (0), // to avoid Purify UMR
+ pbase_saved_ (0), // to avoid Purify UMR
+ get_mode_ (1),
+ put_mode_ (2),
+ mode_ (io_mode),
+ streambuf_size_ (streambuf_size),
+ recv_timeout_ (NULL)
+{
+ (void)reset_get_buffer ();
+ (void)reset_put_buffer ();
+}
+
+u_int
+ACE_Streambuf::streambuf_size (void)
+{
+ return streambuf_size_;
+}
+
+// Return the number of bytes not yet gotten. eback + get_waiting =
+// gptr.
+
+u_int
+ACE_Streambuf::get_waiting (void)
+{
+ return this->gptr_saved_ - this->eback_saved_;
+}
+
+// Return the number of bytes in the get area (includes some already
+// gotten); eback + get_avail = egptr.
+
+u_int
+ACE_Streambuf::get_avail (void)
+{
+ return this->egptr_saved_ - this->eback_saved_;
+}
+
+// Return the number of bytes to be 'put' onto the stream media.
+// pbase + put_avail = pptr.
+
+u_int
+ACE_Streambuf::put_avail (void)
+{
+ return this->pptr_saved_ - this->pbase_saved_;
+}
+
+// Typical usage:
+//
+// u_int newGptr = otherStream->get_waiting ();
+// u_int newEgptr = otherStream->get_avail ();
+// char * newBuf = otherStream->reset_get_buffer ();
+// char * oldgetbuf = myStream->reset_get_buffer (newBuf, otherStream->streambuf_size (), newGptr, newEgptr);
+//
+// 'myStream' now has the get buffer of 'otherStream' and can use it in any way.
+// 'otherStream' now has a new, empty get buffer.
+
+char *
+ACE_Streambuf::reset_get_buffer (char *newBuffer,
+ u_int _streambuf_size,
+ u_int _gptr,
+ u_int _egptr)
+{
+ char * rval = this->eback_saved_;
+
+ // The get area is where the iostream will get data from. This is
+ // our read buffer. There are three pointers which describe the
+ // read buffer:
+ //
+ // eback () - The beginning of the buffer. Also the furthest
+ // point at which putbacks can be done. Hence the name.
+ //
+ // gptr () - Where the next character is to be got from.
+ //
+ // egptr () - One position beyond the last get-able character.
+ //
+ // So that we can switch quicky from read to write mode without
+ // any data copying, we keep copies of these three pointers in
+ // the variables below. Initially, they all point to the beginning
+ // of our read-dedicated buffer.
+ //
+ if (newBuffer)
+ {
+ if (streambuf_size_ != _streambuf_size)
+ return NULL;
+ this->eback_saved_ = newBuffer;
+ }
+ else
+ ACE_NEW_RETURN (this->eback_saved_,
+ char[streambuf_size_],
+ 0);
+
+ this->gptr_saved_ = this->eback_saved_ + _gptr;
+ this->egptr_saved_ = this->eback_saved_ + _egptr;
+
+ // Disable the get area initially. This will cause underflow to be
+ // invoked on the first get operation.
+ setg (0, 0, 0);
+
+ reset_base ();
+
+ return rval;
+}
+
+// Typical usage:
+//
+// u_int newPptr = otherStream->put_avail ();
+// char * newBuf = otherStream->reset_put_buffer ();
+// char * oldputbuf = otherStream->reset_put_buffer (newBuf, otherStream->streambuf_size (), newPptr);
+
+char *
+ACE_Streambuf::reset_put_buffer (char *newBuffer,
+ u_int _streambuf_size,
+ u_int _pptr)
+{
+ char *rval = this->pbase_saved_;
+
+ // The put area is where the iostream will put data that needs to be
+ // sent to the peer. This becomes our write buffer. The three
+ // pointers which maintain this area are:
+ //
+ // pbase () - The beginning of the put area.
+ //
+ // pptr () - Where the next character is to be put.
+ //
+ // epptr () - One beyond the last valid position for putting.
+ //
+ // Again to switch quickly between modes, we keep copies of
+ // these three pointers.
+ //
+ if (newBuffer)
+ {
+ if (streambuf_size_ != _streambuf_size)
+ return NULL;
+ this->pbase_saved_ = newBuffer;
+ }
+ else
+ ACE_NEW_RETURN (this->pbase_saved_,
+ char[streambuf_size_],
+ 0);
+
+ this->pptr_saved_ = this->pbase_saved_ + _pptr;
+ this->epptr_saved_ = this->pbase_saved_ + streambuf_size_;
+
+ // Disable the put area. Overflow will be called by the first call
+ // to any put operator.
+ setp (0, 0);
+
+ reset_base ();
+
+ return rval;
+}
+
+void
+ACE_Streambuf::reset_base (void)
+{
+ // Until we experience the first get or put operation, we do not
+ // know what our current IO mode is.
+ this->cur_mode_ = 0;
+
+ // The common area used for reading and writting is called "base".
+ // We initialize it this way so that the first get/put operation
+ // will have to "allocate" base. This allocation will set base to
+ // the appropriate specific buffer and set the mode to the correct
+ // value.
+ setb (0, 0);
+}
+
+// If the default allocation strategey were used the common buffer
+// would be deleted when the object destructs. Since we are providing
+// separate read/write buffers, it is up to us to manage their memory.
+
+ACE_Streambuf::~ACE_Streambuf (void)
+{
+ delete [] this->eback_saved_;
+ delete [] this->pbase_saved_;
+}
+
+u_char ACE_Streambuf::timeout (void)
+{
+ u_char rval = this->timeout_;
+ this->timeout_ = 0;
+ return rval;
+}
+
+#endif /* !ACE_LACKS_ACE_IOSTREAM */
+#endif /* ACE_IOSTREAM_C */
diff --git a/ace/IPC/IOStream.h b/ace/IPC/IOStream.h
new file mode 100644
index 00000000000..89ce9fb31d5
--- /dev/null
+++ b/ace/IPC/IOStream.h
@@ -0,0 +1,513 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file IOStream.h
+ *
+ * $Id$
+ *
+ * @author James CE Johnson <jcej@lads.com>
+ * @author Jim Crossley <jim@lads.com>
+ */
+//=============================================================================
+
+
+#ifndef ACE_IOSTREAM_H
+#define ACE_IOSTREAM_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// This is a temporary restriction - ACE_IOStream is only enabled if the
+// compiler does not supply the standard C++ library (and standard iostreams)
+// or, if it does, the platform is explicitly set to use old iostreams
+// by its config.h file.
+// This restriction is recorded in Bugzilla entry 857.
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && (ACE_HAS_STANDARD_CPP_LIBRARY == 1)
+# if !defined (ACE_USES_OLD_IOSTREAMS) && !defined (ACE_LACKS_ACE_IOSTREAM)
+# define ACE_LACKS_ACE_IOSTREAM
+# endif /* !ACE_USES_OLD_IOSTREAMS && !ACE_LACKS_ACE_IOSTREAM */
+#endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+#include "ace/streams.h"
+
+#if defined (ACE_HAS_STRING_CLASS)
+#if defined (ACE_WIN32) && defined (_MSC_VER)
+typedef CString ACE_IOStream_String;
+#else
+#if !defined (ACE_HAS_STDCPP_STL_INCLUDES)
+#include /**/ <String.h>
+typedef String ACE_IOStream_String;
+#else
+#include /**/ <string>
+
+#if defined(ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
+typedef std::string ACE_IOStream_String;
+#else
+typedef string ACE_IOStream_String;
+#endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
+#endif /* ! ACE_HAS_STDCPP_STL_INCLUDES */
+#endif /* ACE_WIN32 && defined (_MSC_VER) */
+
+#if defined (__DECCXX_VER)
+# if __DECCXX_VER < 50700000
+# include /**/ <stl_macros>
+# else
+# include /**/ <stdcomp>
+# endif /* __DECCXX_VER < 50700000 */
+#endif /* __DECCXX_VER */
+
+class ACE_Export ACE_Quoted_String : public ACE_IOStream_String
+{
+public:
+ inline ACE_Quoted_String (void) { *this = ""; }
+ inline ACE_Quoted_String (const char *c) { *this = ACE_IOStream_String (c); }
+ inline ACE_Quoted_String (const ACE_IOStream_String &s) { *this = s; }
+ inline ACE_Quoted_String &operator= (const ACE_IOStream_String& s)
+ {
+ return (ACE_Quoted_String &) ACE_IOStream_String::operator= (s);
+ }
+ inline ACE_Quoted_String &operator = (const char c) {
+ return (ACE_Quoted_String &) ACE_IOStream_String::operator= (c);
+ }
+ inline ACE_Quoted_String &operator = (const char *c) {
+ return (ACE_Quoted_String &) ACE_IOStream_String::operator= (c);
+ }
+ inline int operator < (const ACE_Quoted_String &s) const {
+ return *(ACE_IOStream_String *) this < (ACE_IOStream_String) s;
+ }
+#if defined (ACE_WIN32) && defined (_MSC_VER)
+ inline int length (void) { return this->GetLength (); }
+#endif /* ACE_WIN32 && defined (_MSC_VER) */
+};
+
+#endif /* ACE_HAS_STRING_CLASS */
+
+/**
+ * @class ACE_Streambuf
+ *
+ * @brief Create your custom streambuf by providing and ACE_*_Stream
+ * object to this template. I have tested it with
+ * ACE_SOCK_Stream and it should work fine for others as well.
+ *
+ * For any iostream object, the real work is done by the
+ * underlying streambuf class. That is what we create here.
+ * A streambuf has an internal buffer area into which data is
+ * read and written as the iostream requests and provides data.
+ * At some point during the read process, the iostream will
+ * realize that the streambuf has no more data. The underflow
+ * function of the streambuf is then called.
+ * Likewise, during the write process, the iostream will
+ * eventually notice that the streabuf's buffer has become full
+ * and will invoke the overflow function.
+ * The empty/full state of the read/write "buffers" are
+ * controled by two sets pointers. One set is dedicated to
+ * read, the other to write. These pointers, in turn, reference
+ * a common buffer that is to be shared by both read and write
+ * operations. It is this common buffer to which data is
+ * written and from which it is read.
+ * The common buffer is used by functions of the streambuf as
+ * well as the iostream. Because of this and the fact that it
+ * is "shared" by both read and write operators, there is a
+ * danger of data corruption if read and write operations are
+ * allowed to take place "at the same time".
+ * To prevent data corruption, we manipulate the read and write
+ * pointer sets so that the streambuf is in either a read-mode
+ * or write-mode at all times and can never be in both modes at
+ * the same time.
+ * In the constructor: set the read and write sets to NULL This
+ * causes the underflow or overflow operators to be invoked at
+ * the first IO activity of the iostream.
+ * In the underflow function we arrange for the common buffer to
+ * reference our read buffer and for the write pointer set to be
+ * disabled. If a write operation is performed by the iostream
+ * this will cause the overflow function to be invoked.
+ * In the overflow function we arrange for the common buffer to
+ * reference our write buffer and for the read pointer set to be
+ * disabled. This causes the underflow function to be invoked
+ * when the iostream "changes our mode".
+ * The overflow function will also invoke the send_n function to
+ * flush the buffered data to our peer. Similarly, the sync and
+ * syncout functions will cause send_n to be invoked to send the
+ * data.
+ * Since socket's and the like do not support seeking, there can
+ * be no method for "syncing" the input. However, since we
+ * maintain separate read/write buffers, no data is lost by
+ * "syncing" the input. It simply remains buffered.
+ */
+class ACE_Export ACE_Streambuf : public streambuf
+{
+public:
+
+ /**
+ * If the default allocation strategey were used the common buffer
+ * would be deleted when the object destructs. Since we are
+ * providing separate read/write buffers, it is up to us to manage
+ * their memory.
+ */
+ virtual ~ACE_Streambuf (void);
+
+ /// Get the current Time_Value pointer and provide a new one.
+ ACE_Time_Value *recv_timeout (ACE_Time_Value *tv = NULL);
+
+ /**
+ * Use this to allocate a new/different buffer for put operations.
+ * If you do not provide a buffer pointer, one will be allocated.
+ * That is the preferred method. If you do provide a buffer, the
+ * size must match that being used by the get buffer. If
+ * successful, you will receive a pointer to the current put buffer.
+ * It is your responsibility to delete this memory when you are done
+ * with it.
+ */
+ char *reset_put_buffer (char *newBuffer = NULL,
+ u_int _streambuf_size = 0,
+ u_int _pptr = 0 );
+
+ /// Return the number of bytes to be 'put' onto the stream media.
+ /// pbase + put_avail = pptr
+ u_int put_avail (void);
+
+ /**
+ * Use this to allocate a new/different buffer for get operations.
+ * If you do not provide a buffer pointer, one will be allocated.
+ * That is the preferred method. If you do provide a buffer, the
+ * size must match that being used by the put buffer. If
+ * successful, you will receive a pointer to the current get buffer.
+ * It is your responsibility to delete this memory when you are done
+ * with it.
+ */
+ char *reset_get_buffer (char *newBuffer = NULL,
+ u_int _streambuf_size = 0,
+ u_int _gptr = 0,
+ u_int _egptr = 0);
+
+ /// Return the number of bytes not yet gotten. eback + get_waiting =
+ /// gptr
+ u_int get_waiting (void);
+
+ /// Return the number of bytes in the get area (includes some already
+ /// gotten); eback + get_avail = egptr
+ u_int get_avail (void);
+
+ /// Query the streambuf for the size of its buffers.
+ u_int streambuf_size (void);
+
+ /// Did we take an error because of an IO operation timeout? Note:
+ /// Invoking this resets the flag.
+ u_char timeout (void);
+
+protected:
+ ACE_Streambuf (u_int streambuf_size,
+ int io_mode);
+
+ /// Sync both input and output. See syncin/syncout below for
+ /// descriptions.
+ virtual int sync (void);
+
+ // = Signatures for the underflow/overflow discussed above.
+ virtual int underflow (void);
+
+ /// The overflow function receives the character which caused the
+ /// overflow.
+ virtual int overflow (int = EOF);
+
+ /// Resets the <base> pointer and streambuf mode. This is used
+ /// internally when get/put buffers are allocatd.
+ void reset_base (void);
+
+protected:
+ // = Two pointer sets for manipulating the read/write areas.
+ char *eback_saved_;
+ char *gptr_saved_;
+ char *egptr_saved_;
+ char *pbase_saved_;
+ char *pptr_saved_;
+ char *epptr_saved_;
+
+ // = With cur_mode_ we keep track of our current IO mode.
+
+ // This helps us to optimize the underflow/overflow functions.
+ u_char cur_mode_;
+ const u_char get_mode_;
+ const u_char put_mode_;
+
+ /// mode tells us if we're working for an istream, ostream, or
+ /// iostream.
+ int mode_;
+
+ /// This defines the size of the input and output buffers. It can be
+ /// set by the object constructor.
+ const u_int streambuf_size_;
+
+ /// Did we take an error because of an IO operation timeout?
+ u_char timeout_;
+
+ /// We want to allow the user to provide Time_Value pointers to
+ /// prevent infinite blocking while waiting to receive data.
+ ACE_Time_Value recv_timeout_value_;
+ ACE_Time_Value *recv_timeout_;
+
+ /**
+ * syncin is called when the input needs to be synced with the
+ * source file. In a filebuf, this results in the <seek> system
+ * call being used. We can't do that on socket-like connections, so
+ * this does basically nothing. That's safe because we have a
+ * separate read buffer to maintain the already-read data. In a
+ * filebuf, the single common buffer is used forcing the <seek>
+ * call.
+ */
+ int syncin (void);
+
+ /// syncout is called when the output needs to be flushed. This is
+ /// easily done by calling the peer's send_n function.
+ int syncout (void);
+
+ /// flushbuf is the worker of syncout. It is a separate function
+ /// because it gets used sometimes in different context.
+ int flushbuf (void);
+
+ /**
+ * fillbuf is called in a couple of places. This is the worker of
+ * underflow. It will attempt to fill the read buffer from the
+ * peer.
+ */
+ int fillbuf (void);
+
+ /**
+ * Used by fillbuf and others to get exactly one byte from the peer.
+ * recv_n is used to be sure we block until something is available.
+ * It is virtual because we really need to override it for
+ * datagram-derived objects.
+ */
+ virtual int get_one_byte (void);
+
+ /**
+ * Stream connections and "unconnected connections" (ie --
+ * datagrams) need to work just a little differently. We derive
+ * custom Streambuf objects for them and provide these functions at
+ * that time.
+ */
+ virtual ssize_t send (char *buf,
+ ssize_t len) = 0;
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ ACE_Time_Value *tv = NULL) = 0;
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv = NULL) = 0;
+ virtual ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = NULL) = 0;
+
+ virtual ACE_HANDLE get_handle (void);
+
+#if defined (ACE_HAS_STANDARD_CPP_LIBRARY) && (ACE_HAS_STANDARD_CPP_LIBRARY != 0) && !defined (ACE_USES_OLD_IOSTREAMS)
+ char *base (void) const
+ {
+ return cur_mode_ == get_mode_ ? eback_saved_
+ : cur_mode_ == put_mode_ ? pbase_saved_
+ : 0;
+ }
+ char *ebuf (void) const
+ {
+ return cur_mode_ == 0 ? 0 : base () + streambuf_size_;
+ }
+
+ int blen (void) const
+ {
+ return streambuf_size_;
+ }
+
+ void setb (char* b, char* eb, int /* a */=0)
+ {
+ setbuf (b, (eb - b));
+ }
+
+ int out_waiting (void)
+ {
+ return pptr () - pbase ();
+ }
+#endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+// These typedefs are provided by G++ (on some systems?) without the
+// trailing '_'. Since we can't count on 'em, I've defined them to
+// what GNU wants here.
+//
+typedef ios& (*__manip_)(ios&);
+typedef istream& (*__imanip_)(istream&);
+typedef ostream& (*__omanip_)(ostream&);
+
+// Trying to do something like is shown below instead of using the
+// __*manip typedefs causes Linux do segfault when "<<endl" is done.
+//
+// virtual MT& operator<<(ios& (*func)(ios&)) { (*func)(*this); return *this; }
+
+// This macro defines the get operator for class MT into datatype DT.
+// We will use it below to quickly override most (all?) iostream get
+// operators. Notice how the <ipfx> and <isfx> functions are used.
+
+#define GET_SIG(MT,DT) inline virtual MT& operator>> (DT v)
+#if defined (__KCC) || (defined (__SUNPRO_CC) && __SUNPRO_CC > 0x510)
+#define GET_CODE { \
+ if (ipfx (0)) \
+ { \
+ (*((istream*)this)) >> (v); \
+ } \
+ isfx (); \
+ return *this; \
+ }
+#else
+#define GET_CODE { \
+ if (ipfx (0)) \
+ { \
+ iostream::operator>> (v); \
+ } \
+ isfx (); \
+ return *this; \
+ }
+#endif /* __KCC */
+#define GET_PROT(MT,DT,CODE) GET_SIG(MT,DT) CODE
+#define GET_FUNC(MT,DT) GET_PROT(MT,DT,GET_CODE)
+
+// This macro defines the put operator for class MT into datatype DT.
+// We will use it below to quickly override most (all?) iostream put
+// operators. Notice how the <opfx> and <osfx> functions are used.
+
+#define PUT_SIG(MT,DT) inline virtual MT& operator<< (DT v)
+#if defined (__KCC) || (defined (__SUNPRO_CC) && __SUNPRO_CC > 0x510)
+#define PUT_CODE { \
+ if (opfx ()) \
+ { \
+ (*((ostream *) this)) << (v); \
+ } \
+ osfx (); \
+ return *this; \
+ }
+#else
+#define PUT_CODE { \
+ if (opfx ()) \
+ { \
+ iostream::operator<< (v); \
+ } \
+ osfx (); \
+ return *this; \
+ }
+#endif /* __KCC */
+#define PUT_PROT(MT,DT,CODE) PUT_SIG(MT,DT) CODE
+#define PUT_FUNC(MT,DT) PUT_PROT(MT,DT,PUT_CODE)
+
+
+// These are necessary in case somebody wants to derive from us and
+// override one of these with a custom approach.
+
+#if defined (ACE_LACKS_CHAR_STAR_RIGHT_SHIFTS)
+#define GET_FUNC_SET0(MT,CODE,CODE2) \
+ GET_PROT(MT,short &,CODE) \
+ GET_PROT(MT,u_short &,CODE) \
+ GET_PROT(MT,int &,CODE) \
+ GET_PROT(MT,u_int &,CODE) \
+ GET_PROT(MT,long &,CODE) \
+ GET_PROT(MT,u_long &,CODE) \
+ GET_PROT(MT,float &,CODE) \
+ GET_PROT(MT,double &,CODE) \
+ GET_PROT(MT,char &,CODE) \
+ GET_PROT(MT,u_char &,CODE) \
+ GET_PROT(MT,char *,CODE) \
+ inline virtual MT& operator>>(__omanip_ func) CODE2 \
+ inline virtual MT& operator>>(__manip_ func) CODE2
+#elif defined (ACE_LACKS_CHAR_RIGHT_SHIFTS)
+#define GET_FUNC_SET0(MT,CODE,CODE2) \
+ GET_PROT(MT,short &,CODE) \
+ GET_PROT(MT,u_short &,CODE) \
+ GET_PROT(MT,int &,CODE) \
+ GET_PROT(MT,u_int &,CODE) \
+ GET_PROT(MT,long &,CODE) \
+ GET_PROT(MT,u_long &,CODE) \
+ GET_PROT(MT,float &,CODE) \
+ GET_PROT(MT,double &,CODE) \
+ inline virtual MT& operator>>(__omanip_ func) CODE2 \
+ inline virtual MT& operator>>(__manip_ func) CODE2
+#else
+#define GET_FUNC_SET0(MT,CODE,CODE2) \
+ GET_PROT(MT,short &,CODE) \
+ GET_PROT(MT,u_short &,CODE) \
+ GET_PROT(MT,int &,CODE) \
+ GET_PROT(MT,u_int &,CODE) \
+ GET_PROT(MT,long &,CODE) \
+ GET_PROT(MT,u_long &,CODE) \
+ GET_PROT(MT,float &,CODE) \
+ GET_PROT(MT,double &,CODE) \
+ GET_PROT(MT,char &,CODE) \
+ GET_PROT(MT,u_char &,CODE) \
+ GET_PROT(MT,char *,CODE) \
+ GET_PROT(MT,u_char *,CODE) \
+ inline virtual MT& operator>>(__omanip_ func) CODE2 \
+ inline virtual MT& operator>>(__manip_ func) CODE2
+#endif
+
+#define PUT_FUNC_SET0(MT,CODE,CODE2) \
+ PUT_PROT(MT,short,CODE) \
+ PUT_PROT(MT,u_short,CODE) \
+ PUT_PROT(MT,int,CODE) \
+ PUT_PROT(MT,u_int,CODE) \
+ PUT_PROT(MT,long,CODE) \
+ PUT_PROT(MT,u_long,CODE) \
+ PUT_PROT(MT,float,CODE) \
+ PUT_PROT(MT,double,CODE) \
+ PUT_PROT(MT,char,CODE) \
+ PUT_PROT(MT,u_char,CODE) \
+ PUT_PROT(MT,const char *,CODE) \
+ PUT_PROT(MT,u_char *,CODE) \
+ PUT_PROT(MT,void *,CODE) \
+ inline virtual MT& operator<<(__omanip_ func) CODE2 \
+ inline virtual MT& operator<<(__manip_ func) CODE2
+
+#if defined (ACE_LACKS_SIGNED_CHAR)
+ #define GET_FUNC_SET1(MT,CODE,CODE2) GET_FUNC_SET0(MT,CODE,CODE2)
+ #define PUT_FUNC_SET1(MT,CODE,CODE2) PUT_FUNC_SET0(MT,CODE,CODE2)
+#else
+#if defined (ACE_LACKS_CHAR_STAR_RIGHT_SHIFTS)
+ #define GET_FUNC_SET1(MT,CODE,CODE2) \
+ GET_PROT(MT,signed char &,CODE) \
+ GET_FUNC_SET0(MT,CODE,CODE2)
+#else
+ #define GET_FUNC_SET1(MT,CODE,CODE2) \
+ GET_PROT(MT,signed char &,CODE) \
+ GET_PROT(MT,signed char *,CODE) \
+ GET_FUNC_SET0(MT,CODE,CODE2)
+#endif
+
+ #define PUT_FUNC_SET1(MT,CODE,CODE2) \
+ PUT_FUNC(MT,signed char) \
+ PUT_FUNC(MT,const signed char *) \
+ PUT_FUNC_SET0(MT,CODE,CODE2)
+#endif /* ACE_LACKS_SIGNED_CHAR */
+
+#define GET_MANIP_CODE { if (ipfx ()) { (*func) (*this); } isfx (); return *this; }
+#define PUT_MANIP_CODE { if (opfx ()) { (*func) (*this); } osfx (); return *this; }
+
+#define GET_FUNC_SET(MT) GET_FUNC_SET1(MT,GET_CODE,GET_MANIP_CODE)
+#define PUT_FUNC_SET(MT) PUT_FUNC_SET1(MT,PUT_CODE,PUT_MANIP_CODE)
+#define GETPUT_FUNC_SET(MT) GET_FUNC_SET(MT) PUT_FUNC_SET(MT)
+
+#define GET_SIG_SET(MT) GET_FUNC_SET1(MT,= 0;,= 0;)
+#define PUT_SIG_SET(MT) PUT_FUNC_SET1(MT,= 0;,= 0;)
+#define GETPUT_SIG_SET(MT) GET_SIG_SET(MT) PUT_SIG_SET(MT)
+
+// Include the templates here.
+#include "ace/IOStream_T.h"
+#endif /* !ACE_LACKS_ACE_IOSTREAM && ACE_USES_OLD_IOSTREAMS */
+
+#include "ace/post.h"
+#endif /* ACE_IOSTREAM_H */
diff --git a/ace/IPC/IOStream_T.cpp b/ace/IPC/IOStream_T.cpp
new file mode 100644
index 00000000000..176f47afc17
--- /dev/null
+++ b/ace/IPC/IOStream_T.cpp
@@ -0,0 +1,210 @@
+// $Id$
+
+#ifndef ACE_IOSTREAM_T_C
+#define ACE_IOSTREAM_T_C
+
+#include "ace/IOStream_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, IOStream_T, "$Id$")
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+#if defined (ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION) && defined (__GNUG__)
+# if !defined (ACE_IOSTREAM_T_H)
+ // _Only_ define this when compiling this .cpp file standalone, not
+ // when instantiating templates. Its purpose is to provide something
+ // for global constructors and destructors to be tied to. Without it,
+ // they would be tied to the file(name). With Cygnus g++ 2.7.2/VxWorks,
+ // that name is used directly in variable names in the munched ctor/dtor
+ // file. That name contains a ".", so it's not a legal C variable name.
+ // The root of all this trouble is a static instance (of Iostream_init)
+ // declared in the iostream.h header file.
+ int ACE_IOStream_global_of_builtin_type_to_avoid_munch_problems = 0;
+# endif /* ! ACE_IOSTREAM_T_H */
+#endif /* ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION && __GNUG__ */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/IOStream_T.i"
+#endif /* !__ACE_INLINE__ */
+
+// We will be given a STREAM by the iostream object which creates us.
+// See the ACE_IOStream template for how that works. Like other
+// streambuf objects, we can be input-only, output-only or both.
+
+template <class STREAM>
+ACE_Streambuf_T<STREAM>::ACE_Streambuf_T (STREAM *peer,
+ u_int streambuf_size,
+ int io_mode)
+ : ACE_Streambuf (streambuf_size, io_mode),
+ peer_ (peer)
+{
+ // A streambuf allows for unbuffered IO where every character is
+ // read as requested and written as provided. To me, this seems
+ // terribly inefficient for socket-type operations, so I've disabled
+ // it. All of the work would be done by the underflow/overflow
+ // functions anyway and I haven't implemented anything there to
+ // support unbuffered IO.
+
+#if !defined (ACE_LACKS_UNBUFFERED_STREAMBUF)
+ this->unbuffered (0);
+#endif /* ! ACE_LACKS_UNBUFFERED_STREAMBUF */
+
+ // Linebuffered is similar to unbuffered. Again, I don't have any
+ // need for this and I don't see the advantage. I believe this
+ // would have to be supported by underflow/overflow to be effective.
+#if !defined (ACE_LACKS_LINEBUFFERED_STREAMBUF)
+ this->linebuffered (0);
+#endif /* ! ACE_LACKS_LINEBUFFERED_STREAMBUF */
+}
+
+// The typical constructor. This will initiailze your STREAM and then
+// setup the iostream baseclass to use a custom streambuf based on
+// STREAM.
+
+template <class STREAM>
+ACE_IOStream<STREAM>::ACE_IOStream (STREAM &stream,
+ u_int streambuf_size)
+ : iostream (0),
+ STREAM (stream)
+{
+ ACE_NEW (streambuf_,
+ ACE_Streambuf_T<STREAM> ((STREAM *) this,
+ streambuf_size));
+ iostream::init (this->streambuf_);
+}
+
+template <class STREAM>
+ACE_IOStream<STREAM>::ACE_IOStream (u_int streambuf_size)
+ : iostream (0)
+{
+ ACE_NEW (this->streambuf_,
+ ACE_Streambuf_T<STREAM> ((STREAM *) this,
+ streambuf_size));
+ iostream::init (this->streambuf_);
+}
+
+// We have to get rid of the streambuf_ ourselves since we gave it to
+// iostream ()
+
+template <class STREAM>
+ACE_IOStream<STREAM>::~ACE_IOStream (void)
+{
+ delete this->streambuf_;
+}
+
+// The only ambituity in the multiple inheritance is the close ()
+// function.
+
+template <class STREAM> int
+ACE_IOStream<STREAM>::close (void)
+{
+ return STREAM::close ();
+}
+
+template <class STREAM> ACE_IOStream<STREAM> &
+ACE_IOStream<STREAM>::operator>> (ACE_Time_Value *&tv)
+{
+ ACE_Time_Value *old_tv = this->streambuf_->recv_timeout (tv);
+ tv = old_tv;
+ return *this;
+}
+
+#if defined (ACE_HAS_STRING_CLASS)
+
+// A simple string operator. The base iostream has 'em for char* but
+// that isn't always the best thing for a String. If we don't provide
+// our own here, we may not get what we want.
+
+template <class STREAM> ACE_IOStream<STREAM> &
+ACE_IOStream<STREAM>::operator>> (ACE_IOStream_String &v)
+{
+ if (ipfx0 ())
+ {
+ char c;
+ this->get (c);
+
+ for (v = c;
+ this->get (c) && !isspace (c);
+ v += c)
+ continue;
+ }
+
+ isfx ();
+
+ return *this;
+}
+
+template <class STREAM> ACE_IOStream<STREAM> &
+ACE_IOStream<STREAM>::operator<< (ACE_IOStream_String &v)
+{
+ if (opfx ())
+ {
+#if defined (ACE_WIN32) && defined (_MSC_VER)
+ for (int i = 0; i < v.GetLength (); ++i)
+#else
+ for (u_int i = 0; i < (u_int) v.length (); ++i)
+#endif /* ACE_WIN32 && defined (_MSC_VER) */
+ this->put (v[i]);
+ }
+
+ osfx ();
+
+ return *this;
+}
+
+// A more clever put operator for strings that knows how to deal with
+// quoted strings containing back-quoted quotes.
+
+template <class STREAM> STREAM &
+operator>> (STREAM &stream,
+ ACE_Quoted_String &str)
+{
+ char c;
+
+ if (!(stream >> c)) // eat space up to the first char
+ // stream.set (ios::eofbit|ios::failbit);
+ return stream;
+
+ str = ""; // Initialize the string
+
+ // if we don't have a quote, append until we see space
+ if (c != '"')
+ for (str = c; stream.get (c) && !isspace (c); str += c)
+ continue;
+ else
+ for (; stream.get (c) && c != '"'; str += c)
+ if (c == '\\')
+ {
+ stream.get (c);
+ if (c != '"')
+ str += '\\';
+ }
+
+ return stream;
+}
+
+template <class STREAM> STREAM &
+operator<< (STREAM &stream,
+ ACE_Quoted_String &str)
+{
+ stream.put ('"');
+
+ for (u_int i = 0; i < str.length (); ++i)
+ {
+ if (str[i] == '"')
+ stream.put ('\\');
+ stream.put (str[i]);
+ }
+
+ stream.put ('"');
+
+ return stream;
+}
+
+#endif /* ACE_HAS_STRING_CLASS */
+#endif /* ACE_LACKS_ACE_IOSTREAM */
+#endif /* ACE_IOSTREAM_T_C */
diff --git a/ace/IPC/IOStream_T.h b/ace/IPC/IOStream_T.h
new file mode 100644
index 00000000000..b853cd0f1f8
--- /dev/null
+++ b/ace/IPC/IOStream_T.h
@@ -0,0 +1,289 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file IOStream_T.h
+ *
+ * $Id$
+ *
+ * @author James CE Johnson <jcej@lads.com>
+ * @author Jim Crossley <jim@lads.com>
+ *
+ * This file should not be #included directly by application
+ * code. Instead, it should #include "ace/IOStream.h". That's because
+ * we only put some conditional compilations in that file.
+ */
+//=============================================================================
+
+
+#ifndef ACE_IOSTREAM_T_H
+#define ACE_IOSTREAM_T_H
+#include "ace/pre.h"
+
+#include "ace/IOStream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+#include "ace/INET_Addr.h"
+#include "ace/Handle_Set.h"
+
+#if defined (ACE_HAS_STRING_CLASS)
+template <class STREAM> STREAM & operator>> (STREAM &stream, ACE_Quoted_String &str);
+template <class STREAM> STREAM & operator<< (STREAM &stream, ACE_Quoted_String &str);
+#endif /* defined (ACE_HAS_STRING_CLASS) */
+
+template <class STREAM>
+class ACE_Streambuf_T : public ACE_Streambuf
+{
+public:
+ /**
+ * We will be given a STREAM by the iostream object which creates
+ * us. See the ACE_IOStream template for how that works. Like
+ * other streambuf objects, we can be input-only, output-only or
+ * both.
+ */
+ ACE_Streambuf_T (STREAM *peer,
+ u_int streambuf_size = ACE_STREAMBUF_SIZE,
+ int io_mode = ios::in | ios::out);
+
+ virtual ssize_t send (char *buf, ssize_t len);
+
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ ACE_Time_Value *tv = NULL);
+
+ virtual ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value * tv = NULL);
+
+ virtual ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = NULL);
+
+protected:
+ virtual ACE_HANDLE get_handle (void);
+
+ /// This will be our ACE_SOCK_Stream or similar object.
+ STREAM *peer_;
+};
+
+/**
+ * @class ACE_IOStream
+ *
+ * @brief A template adapter for creating an iostream-like object using
+ * an ACE IPC Stream for the actual I/O. Iostreams use an
+ * underlying streambuf object for the IO interface. The
+ * iostream class and derivatives provide you with a host of
+ * convenient operators that access the streambuf.
+ *
+ * We inherit all characteristics of iostream and your <STREAM>
+ * class. When you create a new class from this template, you
+ * can use it anywhere you would have used your original
+ * <STREAM> class.
+ * To create an iostream for your favorite ACE IPC class (e.g.,
+ * <ACE_SOCK_Stream>), feed that class to this template's
+ * <STREAM> parameter, e.g.,
+ * typedef ACE_Svc_Handler<ACE_SOCK_iostream,
+ * ACE_INET_Addr, ACE_NULL_SYNCH>
+ * Service_Handler;
+ * Because the operators in the iostream class are not virtual,
+ * you cannot easily provide overloads in your custom
+ * ACE_IOStream classes. To make these things work correctly,
+ * you need to overload ALL operators of the ACE_IOStream you
+ * create. I've attempted to do that here to make things easier
+ * for you but there are no guarantees.
+ * In the iostream.cpp file is an example of why it is necessary
+ * to overload all of the get/put operators when you want to
+ * customize only one or two.
+ */
+template <class STREAM>
+class ACE_IOStream : public iostream, public STREAM
+{
+public:
+ // = Initialization and termination methods.
+ ACE_IOStream (STREAM &stream,
+ u_int streambuf_size = ACE_STREAMBUF_SIZE);
+
+ /**
+ * The default constructor. This will initiailze your STREAM and
+ * then setup the iostream baseclass to use a custom streambuf based
+ * on STREAM.
+ */
+ ACE_IOStream (u_int streambuf_size = ACE_STREAMBUF_SIZE);
+
+ /// We have to get rid of the <streambuf_> ourselves since we gave it
+ /// to the <iostream> base class;
+ virtual ~ACE_IOStream (void);
+
+ /// The only ambituity in the multiple inheritance is the <close>
+ /// function.
+ virtual int close (void);
+
+ /**
+ * Returns 1 if we're at the end of the <STREAM>, i.e., if the
+ * connection has closed down or an error has occurred, else 0.
+ * Under the covers, <eof> calls the streambuf's <timeout> function
+ * which will reset the timeout flag. As as result, you should save
+ * the return of <eof> and check it instead of calling <eof>
+ * successively.
+ */
+ int eof (void) const;
+
+#if defined (ACE_HAS_STRING_CLASS)
+ /**
+ * A simple string operator. The base <iostream> has them for char*
+ * but that isn't always the best thing for a <String>. If we don't
+ * provide our own here, we may not get what we want.
+ */
+ virtual ACE_IOStream<STREAM> &operator>> (ACE_IOStream_String &v);
+
+ /// The converse of the <String::put> operator.
+ virtual ACE_IOStream<STREAM> &operator<< (ACE_IOStream_String &v);
+
+#endif /* ACE_HAS_STRING_CLASS */
+ // = Using the macros to provide get/set operators.
+ GETPUT_FUNC_SET (ACE_IOStream<STREAM>)
+
+#if defined (ACE_LACKS_IOSTREAM_FX)
+ virtual int ipfx (int noskip = 0)
+ {
+ if (good ())
+ {
+ if (tie () != 0)
+ tie ()->flush ();
+ if (!noskip && flags () & skipws)
+ {
+ int ch;
+ while (isspace (ch = rdbuf ()->sbumpc ()))
+ continue;
+ if (ch != EOF)
+ rdbuf ()->sputbackc (ch);
+ }
+ if (good ())
+ return 1;
+ }
+#if !defined (ACE_WIN32)
+ // MS VC++ 5.0 doesn't declare setstate.
+ setstate (failbit);
+#endif /* !ACE_WIN32 */
+ return (0);
+ }
+ virtual int ipfx0 (void) { return ipfx (0); } // Optimized ipfx(0)
+ virtual int ipfx1 (void) // Optimized ipfx(1)
+ {
+ if (good ())
+ {
+ if (tie () != 0)
+ tie ()->flush ();
+ if (good ())
+ return 1;
+ }
+#if !defined (ACE_WIN32)
+ // MS VC++ 5.0 doesn't declare setstate.
+ setstate (failbit);
+#endif /* !ACE_WIN32 */
+ return (0);
+ }
+ virtual void isfx (void) { return; }
+ virtual int opfx (void)
+ {
+ if (good () && tie () != 0)
+ tie ()->flush ();
+ return good ();
+ }
+ virtual void osfx (void) { if (flags () & unitbuf) flush (); }
+#else
+#if defined (__GNUC__)
+ virtual int ipfx0 (void) { return iostream::ipfx0 (); } // Optimized ipfx(0)
+ virtual int ipfx1 (void) { return iostream::ipfx1 (); } // Optimized ipfx(1)
+#else
+ virtual int ipfx0 (void) { return iostream::ipfx (0); }
+ virtual int ipfx1 (void) { return iostream::ipfx (1); }
+#endif /* __GNUC__ */
+ virtual int ipfx (int need = 0) { return iostream::ipfx (need); }
+ virtual void isfx (void) { iostream::isfx (); }
+ virtual int opfx (void) { return iostream::opfx (); }
+ virtual void osfx (void) { iostream::osfx (); }
+#endif /* ACE_LACKS_IOSTREAM_FX */
+
+ /// Allow the programmer to provide a timeout for read operations.
+ /// Give it a pointer to NULL to block forever.
+ ACE_IOStream<STREAM> & operator>> (ACE_Time_Value *&tv);
+
+protected:
+ /// This is where all of the action takes place. The streambuf_ is
+ /// the interface to the underlying STREAM.
+ ACE_Streambuf_T<STREAM> *streambuf_;
+
+private:
+ // = Private methods.
+
+ // We move these into the private section so that they cannot be
+ // used by the application programmer. This is necessary because
+ // streambuf_ will be buffering IO on the STREAM object. If these
+ // functions were used in your program, there is a danger of getting
+ // the datastream out of sync.
+ ACE_UNIMPLEMENTED_FUNC (ssize_t send (...))
+ ACE_UNIMPLEMENTED_FUNC (ssize_t recv (...))
+ ACE_UNIMPLEMENTED_FUNC (ssize_t send_n (...))
+ ACE_UNIMPLEMENTED_FUNC (ssize_t recv_n (...))
+};
+
+/**
+ * @class ACE_SOCK_Dgram_SC
+ *
+ * @brief "Dgram_SC" is short for "Datagram Self-Contained."
+ *
+ * Datagrams don't have the notion of a "peer". Each send and
+ * receive on a datagram can go to a different peer if you want.
+ * If you're using datagrams for stream activity, you probably
+ * want 'em all to go to (and come from) the same place. That's
+ * what this class is for. Here, we keep an address object so
+ * that we can remember who last sent us data. When we write
+ * back, we're then able to write back to that same address.
+ */
+template <class STREAM>
+class ACE_SOCK_Dgram_SC : public STREAM
+{
+public:
+ ACE_SOCK_Dgram_SC (void);
+ ACE_SOCK_Dgram_SC (STREAM &source,
+ ACE_INET_Addr &dest);
+ ssize_t send_n (char *buf, ssize_t len);
+ ssize_t recv (char *buf,
+ ssize_t len,
+ ACE_Time_Value *tv = NULL);
+ ssize_t recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv = NULL);
+ ssize_t recv_n (char *buf,
+ ssize_t len,
+ int flags = 0,
+ ACE_Time_Value *tv = NULL);
+ int get_remote_addr (ACE_INET_Addr &addr) const;
+
+protected:
+ ACE_INET_Addr peer_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/IOStream_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/IOStream_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("IOStream_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+#endif /* ACE_LACKS_ACE_IOSTREAM */
+#include "ace/post.h"
+#endif /* ACE_IOSTREAM_T_H */
diff --git a/ace/IPC/IOStream_T.i b/ace/IPC/IOStream_T.i
new file mode 100644
index 00000000000..c145eb52cc3
--- /dev/null
+++ b/ace/IPC/IOStream_T.i
@@ -0,0 +1,160 @@
+/* -*- C++ -*- */
+// $Id$
+
+template <class STREAM> ssize_t
+ACE_Streambuf_T<STREAM>::send (char *buf, ssize_t len)
+{
+ return peer_->send_n (buf,len);
+}
+
+template <class STREAM> ssize_t
+ACE_Streambuf_T<STREAM>::recv (char *buf,
+ ssize_t len,
+ ACE_Time_Value *tv)
+{
+ return this->recv (buf, len, 0, tv);
+}
+
+template <class STREAM> ssize_t
+ACE_Streambuf_T<STREAM>::recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value * tv)
+{
+ this->timeout_ = 0;
+ errno = ESUCCESS;
+ ssize_t rval = peer_->recv (buf, len, flags, tv);
+ if (errno == ETIME)
+ this->timeout_ = 1;
+ return rval;
+}
+
+template <class STREAM> ssize_t
+ACE_Streambuf_T<STREAM>::recv_n (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv)
+{
+ this->timeout_ = 0;
+ errno = ESUCCESS;
+ ssize_t rval = peer_->recv_n (buf, len, flags, tv);
+ if (errno == ETIME)
+ this->timeout_ = 1;
+ return rval;
+}
+
+template <class STREAM> ACE_HANDLE
+ACE_Streambuf_T<STREAM>::get_handle (void)
+{
+ return peer_ ? peer_->get_handle () : 0;
+}
+
+template <class STREAM> ACE_INLINE int
+ACE_IOStream<STREAM>::eof (void) const
+{
+ // Get the timeout value of the streambuf
+ ACE_Time_Value *timeout = this->streambuf_->recv_timeout (0);
+
+ // Reset the timeout value of the streambuf.
+ (void) this->streambuf_->recv_timeout (timeout);
+
+ char c;
+ int rval = this->streambuf_->recv_n (&c,
+ sizeof c,
+ MSG_PEEK,
+ timeout);
+
+ // Timeout, not an eof
+ if (this->streambuf_->timeout())
+ return 0;
+
+ // No timeout, got enough data: not eof
+ if (rval == sizeof(char))
+ return 0;
+
+ // No timeout, not enough data: definately eof
+ return 1;
+}
+
+template <class STREAM> ACE_INLINE
+ACE_SOCK_Dgram_SC<STREAM>::ACE_SOCK_Dgram_SC (void)
+{
+}
+
+template <class STREAM> ACE_INLINE
+ACE_SOCK_Dgram_SC<STREAM>::ACE_SOCK_Dgram_SC (STREAM &source,
+ ACE_INET_Addr &dest)
+ : STREAM (source),
+ peer_ (dest)
+{
+}
+
+template <class STREAM> ACE_INLINE ssize_t
+ACE_SOCK_Dgram_SC<STREAM>::send_n (char *buf,
+ ssize_t len)
+{
+ return STREAM::send (buf, len, peer_);
+}
+
+template <class STREAM> ACE_INLINE ssize_t
+ACE_SOCK_Dgram_SC<STREAM>::recv (char *buf,
+ ssize_t len,
+ ACE_Time_Value *tv)
+{
+ return recv (buf, len, 0, tv);
+}
+
+template <class STREAM> ACE_INLINE ssize_t
+ACE_SOCK_Dgram_SC<STREAM>::recv (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv)
+{
+ if (tv != 0)
+ {
+ ACE_HANDLE handle = this->get_handle ();
+ ACE_Handle_Set handle_set;
+
+ handle_set.set_bit (handle);
+
+ switch (ACE_OS::select (int (handle) + 1,
+ (fd_set *) handle_set, // read_fds.
+ (fd_set *) 0, // write_fds.
+ (fd_set *) 0, // exception_fds.
+ tv))
+ {
+ case 0:
+ errno = ETIME;
+ case -1:
+ return -1;
+ default:
+ ; // Do the 'recv' below
+ }
+ }
+
+ int rval = STREAM::recv (buf, len, peer_, flags);
+#if defined (ACE_WIN32)
+ if (rval == SOCKET_ERROR)
+ if (::WSAGetLastError () == WSAEMSGSIZE)
+ if (ACE_BIT_ENABLED (flags, MSG_PEEK))
+ rval = len;
+#endif /* ACE_WIN32 */
+ return rval < len ? rval : len;
+}
+
+template <class STREAM> ACE_INLINE ssize_t
+ACE_SOCK_Dgram_SC<STREAM>::recv_n (char *buf,
+ ssize_t len,
+ int flags,
+ ACE_Time_Value *tv)
+{
+ int rval = this->recv (buf, len, flags, tv);
+ return rval;
+}
+
+template <class STREAM> ACE_INLINE int
+ACE_SOCK_Dgram_SC<STREAM>::get_remote_addr (ACE_INET_Addr &addr) const
+{
+ addr = peer_;
+ return 0;
+}
diff --git a/ace/IPC/IO_SAP.cpp b/ace/IPC/IO_SAP.cpp
new file mode 100644
index 00000000000..f3ad46c46b7
--- /dev/null
+++ b/ace/IPC/IO_SAP.cpp
@@ -0,0 +1,142 @@
+// IO_SAP.cpp
+// $Id$
+
+#include "ace/IO_SAP.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/IO_SAP.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, IO_SAP, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_IO_SAP)
+
+// This is the do-nothing constructor. It does not perform a
+// ACE_OS::open system call.
+
+ACE_IO_SAP::ACE_IO_SAP (void)
+ : handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_IO_SAP::ACE_IO_SAP");
+}
+
+void
+ACE_IO_SAP::dump (void) const
+{
+ ACE_TRACE ("ACE_IO_SAP::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("handle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npid_ = %d"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Cache for the process ID.
+pid_t ACE_IO_SAP::pid_ = 0;
+
+int
+ACE_IO_SAP::enable (int value) const
+{
+ ACE_TRACE ("ACE_IO_SAP::enable");
+ /* First-time in initialization. */
+ if (ACE_IO_SAP::pid_ == 0)
+ ACE_IO_SAP::pid_ = ACE_OS::getpid ();
+
+#if !defined(ACE_WIN32) && !defined (VXWORKS)
+
+ switch (value)
+ {
+#if defined (SIGURG)
+ case SIGURG:
+ case ACE_SIGURG:
+#if defined (F_SETOWN)
+ return ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ ACE_IO_SAP::pid_);
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN */
+#endif /* SIGURG */
+#if defined (SIGIO)
+ case SIGIO:
+ case ACE_SIGIO:
+#if defined (F_SETOWN) && defined (FASYNC)
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ ACE_IO_SAP::pid_) == -1
+ || ACE_Flag_Manip::set_flags (this->handle_,
+ FASYNC) == -1)
+ return -1;
+ break;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN && FASYNC */
+#else // <==
+ ACE_NOTSUP_RETURN (-1);
+#endif /* SIGIO <== */
+ case ACE_NONBLOCK:
+ if (ACE_Flag_Manip::set_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+#else
+ ACE_UNUSED_ARG (value);
+#endif /* !ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_IO_SAP::disable (int value) const
+{
+ ACE_TRACE ("ACE_IO_SAP::disable");
+
+#if !defined(ACE_WIN32) && !defined (VXWORKS)
+ switch (value)
+ {
+#if defined (SIGURG)
+ case SIGURG:
+ case ACE_SIGURG:
+#if defined (F_SETOWN)
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETOWN, 0) == -1)
+ return -1;
+ break;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN */
+#endif /* SIGURG */
+#if defined (SIGIO)
+ case SIGIO:
+ case ACE_SIGIO:
+#if defined (F_SETOWN) && defined (FASYNC)
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ 0) == -1
+ || ACE_Flag_Manip::clr_flags (this->handle_, FASYNC) == -1)
+ return -1;
+ break;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN && FASYNC */
+#else // <==
+ ACE_NOTSUP_RETURN (-1);
+#endif /* SIGIO <== */
+ case ACE_NONBLOCK:
+ if (ACE_Flag_Manip::clr_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#else
+ ACE_UNUSED_ARG (value);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* !ACE_WIN32 */
+}
diff --git a/ace/IPC/IO_SAP.h b/ace/IPC/IO_SAP.h
new file mode 100644
index 00000000000..4cc1d5cda84
--- /dev/null
+++ b/ace/IPC/IO_SAP.h
@@ -0,0 +1,90 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file IO_SAP.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_IO_SAP_H
+#define ACE_IO_SAP_H
+#include "ace/pre.h"
+
+#include "ace/Flag_Manip.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_IO_SAP
+ *
+ * @brief Defines the methods for the base class of the <ACE_IO_SAP>
+ * abstraction, which includes <ACE_FILE> and <ACE_DEV>.
+ */
+class ACE_Export ACE_IO_SAP
+{
+public:
+ enum
+ {
+ /// Be consistent with Winsock
+ INVALID_HANDLE = -1
+ };
+
+ /// Default dtor.
+ ~ACE_IO_SAP (void);
+
+ /// Interface for ioctl.
+ int control (int cmd, void *) const;
+
+ // = Common I/O handle options related to files.
+
+ /**
+ * Enable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int enable (int value) const;
+
+ /**
+ * Disable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int disable (int value) const;
+
+ /// Get the underlying handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Set the underlying handle.
+ void set_handle (ACE_HANDLE handle);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Ensure that ACE_IO_SAP is an abstract base class.
+ ACE_IO_SAP (void);
+
+private:
+ /// Underlying I/O handle.
+ ACE_HANDLE handle_;
+
+ /// Cache the process ID.
+ static pid_t pid_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/IO_SAP.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_IO_SAP_H */
diff --git a/ace/IPC/IO_SAP.i b/ace/IPC/IO_SAP.i
new file mode 100644
index 00000000000..5bb805d48f4
--- /dev/null
+++ b/ace/IPC/IO_SAP.i
@@ -0,0 +1,39 @@
+/* -*- C++ -*- */
+// $Id$
+
+// IO_SAP.i
+
+ASYS_INLINE
+ACE_IO_SAP::~ACE_IO_SAP (void)
+{
+ ACE_TRACE ("ACE_IO_SAP::~ACE_IO_SAP");
+}
+
+// Used to return the underlying handle_.
+
+ASYS_INLINE ACE_HANDLE
+ACE_IO_SAP::get_handle (void) const
+{
+ ACE_TRACE ("ACE_IO_SAP::get_handle");
+ return this->handle_;
+}
+
+// Used to set the underlying handle_.
+
+ASYS_INLINE void
+ACE_IO_SAP::set_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_IO_SAP::set_handle");
+ this->handle_ = handle;
+}
+
+// Provides access to the ACE_OS::ioctl system call.
+
+ASYS_INLINE int
+ACE_IO_SAP::control (int cmd, void *arg) const
+{
+ ACE_TRACE ("ACE_IO_SAP::control");
+ return ACE_OS::ioctl (this->handle_, cmd, arg);
+}
+
+
diff --git a/ace/IPC/Pipe.cpp b/ace/IPC/Pipe.cpp
new file mode 100644
index 00000000000..85f84575717
--- /dev/null
+++ b/ace/IPC/Pipe.cpp
@@ -0,0 +1,235 @@
+// $Id$
+
+#include "ace/Pipe.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/Pipe.i"
+#endif
+
+ACE_RCSID(ace, Pipe, "$Id$")
+
+void
+ACE_Pipe::dump (void) const
+{
+ ACE_TRACE ("ACE_Pipe::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("handles_[0] = %d"), this->handles_[0]));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhandles_[1] = %d"), this->handles_[1]));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_Pipe::open (int buffer_size)
+{
+ ACE_TRACE ("ACE_Pipe::open");
+
+#if defined (ACE_WIN32) || defined (ACE_LACKS_SOCKETPAIR) || defined (__Lynx__)
+ ACE_INET_Addr my_addr;
+ ACE_SOCK_Acceptor acceptor;
+ ACE_SOCK_Connector connector;
+ ACE_SOCK_Stream reader;
+ ACE_SOCK_Stream writer;
+ int result = 0;
+
+ // Bind listener to any port and then find out what the port was.
+ if (acceptor.open (ACE_Addr::sap_any) == -1
+ || acceptor.get_local_addr (my_addr) == -1)
+ result = -1;
+ else
+ {
+ ACE_INET_Addr sv_addr (my_addr.get_port_number (),
+ ACE_LOCALHOST);
+
+ // Establish a connection within the same process.
+ if (connector.connect (writer, sv_addr) == -1)
+ result = -1;
+ else if (acceptor.accept (reader) == -1)
+ {
+ writer.close ();
+ result = -1;
+ }
+ }
+
+ // Close down the acceptor endpoint since we don't need it anymore.
+ acceptor.close ();
+ if (result == -1)
+ return -1;
+
+ this->handles_[0] = reader.get_handle ();
+ this->handles_[1] = writer.get_handle ();
+
+# if !defined (ACE_LACKS_TCP_NODELAY)
+ int one = 1;
+
+ // Make sure that the TCP stack doesn't try to buffer small writes.
+ // Since this communication is purely local to the host it doesn't
+ // affect network performance.
+
+ if (writer.set_option (ACE_IPPROTO_TCP,
+ TCP_NODELAY,
+ &one,
+ sizeof one) == -1)
+ {
+ this->close ();
+ return -1;
+ }
+# endif /* ! ACE_LACKS_TCP_NODELAY */
+
+# if defined (ACE_LACKS_SOCKET_BUFSIZ)
+ ACE_UNUSED_ARG (buffer_size);
+# else /* ! ACE_LACKS_SOCKET_BUFSIZ */
+ if (reader.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ ACE_reinterpret_cast (void *, &buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+ else if (writer.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ ACE_reinterpret_cast (void *, &buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+# endif /* ! ACE_LACKS_SOCKET_BUFSIZ */
+
+#elif defined (ACE_HAS_STREAM_PIPES) || defined(__QNX__)
+ ACE_UNUSED_ARG (buffer_size);
+ if (ACE_OS::pipe (this->handles_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("pipe")),
+ -1);
+
+#if !defined(__QNX__)
+ int arg = RMSGN;
+
+ // Enable "msg no discard" mode, which ensures that record
+ // boundaries are maintained when messages are sent and received.
+ if (ACE_OS::ioctl (this->handles_[0],
+ I_SRDOPT,
+ (void *) arg) == -1
+ || ACE_OS::ioctl (this->handles_[1],
+ I_SRDOPT,
+ (void *) arg) == -1)
+ {
+ this->close ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ioctl")), -1);
+ }
+#endif /* __QNX__ */
+
+#else /* ! ACE_WIN32 && ! ACE_LACKS_SOCKETPAIR && ! ACE_HAS_STREAM_PIPES */
+ if (ACE_OS::socketpair (AF_UNIX,
+ SOCK_STREAM,
+ 0,
+ this->handles_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("socketpair")),
+ -1);
+# if defined (ACE_LACKS_SOCKET_BUFSIZ)
+ ACE_UNUSED_ARG (buffer_size);
+# else /* ! ACE_LACKS_SOCKET_BUFSIZ */
+ if (ACE_OS::setsockopt (this->handles_[0],
+ SOL_SOCKET,
+ SO_RCVBUF,
+ ACE_reinterpret_cast (const char *,
+ &buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+ if (ACE_OS::setsockopt (this->handles_[1],
+ SOL_SOCKET,
+ SO_SNDBUF,
+ ACE_reinterpret_cast (const char *, &buffer_size),
+ sizeof (buffer_size)) == -1
+ && errno != ENOTSUP)
+ {
+ this->close ();
+ return -1;
+ }
+# endif /* ! ACE_LACKS_SOCKET_BUFSIZ */
+#endif /* ! ACE_WIN32 && ! ACE_LACKS_SOCKETPAIR && ! ACE_HAS_STREAM_PIPES */
+ // Point both the read and write HANDLES to the appropriate socket
+ // HANDLEs.
+
+ return 0;
+}
+
+int
+ACE_Pipe::open (ACE_HANDLE handles[2])
+{
+ ACE_TRACE ("ACE_Pipe::open");
+
+ if (this->open () == -1)
+ return -1;
+ else
+ {
+ handles[0] = this->handles_[0];
+ handles[1] = this->handles_[1];
+ return 0;
+ }
+}
+
+// Do nothing...
+
+ACE_Pipe::ACE_Pipe (void)
+{
+ ACE_TRACE ("ACE_Pipe::ACE_Pipe");
+
+ this->handles_[0] = ACE_INVALID_HANDLE;
+ this->handles_[1] = ACE_INVALID_HANDLE;
+}
+
+ACE_Pipe::ACE_Pipe (ACE_HANDLE handles[2])
+{
+ ACE_TRACE ("ACE_Pipe::ACE_Pipe");
+
+ if (this->open (handles) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_Pipe::ACE_Pipe")));
+}
+
+ACE_Pipe::ACE_Pipe (ACE_HANDLE read,
+ ACE_HANDLE write)
+{
+ ACE_TRACE ("ACE_Pipe::ACE_Pipe");
+ this->handles_[0] = read;
+ this->handles_[1] = write;
+}
+
+int
+ACE_Pipe::close (void)
+{
+ ACE_TRACE ("ACE_Pipe::close");
+
+ int result = 0;
+
+ // Note that the following will work even if we aren't closing down
+ // sockets because <ACE_OS::closesocket> will just call <::close> in
+ // that case!
+
+ if (this->handles_[0] != ACE_INVALID_HANDLE)
+ result = ACE_OS::closesocket (this->handles_[0]);
+ this->handles_[0] = ACE_INVALID_HANDLE;
+
+ if (this->handles_[1] != ACE_INVALID_HANDLE)
+ result |= ACE_OS::closesocket (this->handles_[1]);
+ this->handles_[1] = ACE_INVALID_HANDLE;
+
+ return result;
+}
diff --git a/ace/IPC/Pipe.h b/ace/IPC/Pipe.h
new file mode 100644
index 00000000000..d58767b1729
--- /dev/null
+++ b/ace/IPC/Pipe.h
@@ -0,0 +1,86 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Pipe.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_PIPE_H
+#define ACE_PIPE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Pipe
+ *
+ * @brief Provides a bidirectional "pipe" abstraction that is portable
+ * to Windows NT, SVR4 UNIX, and BSD UNIX.
+ *
+ * Uses "name" for lookup in the ACE service repository. Obtains
+ * the object and returns it as the appropriate type.
+ */
+class ACE_Export ACE_Pipe
+{
+public:
+ // = Initialization and termination.
+ /// Default constructor (does nothing...).
+ ACE_Pipe (void);
+
+ /// Open the pipe and initialize the handles.
+ ACE_Pipe (ACE_HANDLE handles[2]);
+
+ /// Initialize the <ACE_Pipe> from the <read> and <write> handles.
+ ACE_Pipe (ACE_HANDLE read, ACE_HANDLE write);
+
+ /// Default dtor. It doesn't close the handles for you.
+ ~ACE_Pipe (void);
+
+ /// Open the pipe and initialize the handles.
+ int open (ACE_HANDLE handles[2]);
+
+ /// Open the pipe, setting the buffer size to the maximum.
+ int open (int buffer_size = ACE_DEFAULT_MAX_SOCKET_BUFSIZ);
+
+ /// Close down the pipe HANDLEs;
+ int close (void);
+
+ // = Accessors.
+
+ /**
+ * This is the "read" side of the pipe. Note, however, that
+ * processes can also write to this handle as well since pipes are
+ * bi-directional.
+ */
+ ACE_HANDLE read_handle (void) const;
+
+ /**
+ * This is the "write" side of the pipe. Note, however, that
+ * processes can also read to this handle as well since pipes are
+ * bi-directional.
+ */
+ ACE_HANDLE write_handle (void) const;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+private:
+ ACE_HANDLE handles_[2];
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/Pipe.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_PIPE_H */
diff --git a/ace/IPC/Pipe.i b/ace/IPC/Pipe.i
new file mode 100644
index 00000000000..0eb87370827
--- /dev/null
+++ b/ace/IPC/Pipe.i
@@ -0,0 +1,25 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Pipe.i
+
+ASYS_INLINE
+ACE_Pipe::~ACE_Pipe (void)
+{
+ ACE_TRACE ("ACE_Pipe::~ACE_Pipe");
+ // Notice that the destructor doesn't close the handles for you.
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_Pipe::read_handle (void) const
+{
+ ACE_TRACE ("ACE_Pipe::read_handle");
+ return this->handles_[0];
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_Pipe::write_handle (void) const
+{
+ ACE_TRACE ("ACE_Pipe::write_handle");
+ return this->handles_[1];
+}
diff --git a/ace/IPC/SPIPE.cpp b/ace/IPC/SPIPE.cpp
new file mode 100644
index 00000000000..0f2be4cc65d
--- /dev/null
+++ b/ace/IPC/SPIPE.cpp
@@ -0,0 +1,63 @@
+// SPIPE.cpp
+// $Id$
+
+#include "ace/SPIPE.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE.i"
+#endif
+
+ACE_RCSID(ace, SPIPE, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE)
+
+// This is the do-nothing constructor.
+
+ACE_SPIPE::ACE_SPIPE (void)
+{
+ // ACE_TRACE ("ACE_SPIPE::ACE_SPIPE");
+}
+
+void
+ACE_SPIPE::dump (void) const
+{
+ ACE_TRACE ("ACE_SPIPE::dump");
+}
+
+// Close down a ACE_SPIPE.
+
+int
+ACE_SPIPE::get_local_addr (ACE_SPIPE_Addr &local_sap) const
+{
+ ACE_TRACE ("ACE_SPIPE::get_local_addr");
+ local_sap = this->local_addr_;
+ return 0;
+}
+
+// Close down the STREAM pipe without removing the rendezvous point.
+
+int
+ACE_SPIPE::close (void)
+{
+ ACE_TRACE ("ACE_SPIPE::close");
+ int result = 0;
+
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ result = ACE_OS::close (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ }
+ return result;
+}
+
+// Close down the STREAM pipe and remove the rendezvous point from the
+// file system.
+
+int
+ACE_SPIPE::remove (void)
+{
+ ACE_TRACE ("ACE_SPIPE::remove");
+ int result = this->close ();
+ return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1 || result == -1 ? -1 : 0;
+}
+
diff --git a/ace/IPC/SPIPE.h b/ace/IPC/SPIPE.h
new file mode 100644
index 00000000000..04e06d71011
--- /dev/null
+++ b/ace/IPC/SPIPE.h
@@ -0,0 +1,100 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SPIPE_H
+#define ACE_SPIPE_H
+#include "ace/pre.h"
+
+#include "ace/IPC_SAP.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SPIPE_Addr.h"
+
+/**
+ * @class ACE_SPIPE
+ *
+ * @brief Defines the member functions for the base class of the
+ * ACE_SPIPE abstraction.
+ *
+ * ACE_SPIPE was designed as a wrapper facade for STREAM pipes. On
+ * Windows, however, ACE_SPIPE is a wrapper for Named Pipes. Therefore,
+ * on Windows, it is better to use the ACE_Proactor or blocking operations
+ * in lieu of using the ACE_Reactor.
+ *
+ * @sa ACE_SPIPE_Acceptor for additional notes on use with ACE_Reactor
+ * on Windows.
+ *
+ * @warning Windows: Works only on Windows NT 4 and higher.
+ * @warning Works on non-Windows platforms only when @c ACE_HAS_STREAM_PIPES
+ * is defined.
+ */
+class ACE_Export ACE_SPIPE : public ACE_IPC_SAP
+{
+public:
+ /// Close down the SPIPE without removing the rendezvous point.
+ /**
+ * Closes the underlying pipe handle and sets this object's handle value
+ * to @c ACE_INVALID_HANDLE.
+ * @return 0 for success; -1 for failure. If a failure occurs, further
+ * error information is available from ACE_OS::last_error().
+ */
+ int close (void);
+
+ /// Close down the SPIPE and remove the rendezvous point from
+ /// the file system.
+ /**
+ * @return 0 for success; -1 for failure. If a failure occurs, further
+ * error information is available from ACE_OS::last_error().
+ */
+ int remove (void);
+
+ /// Return the local address of this endpoint.
+ /**
+ * Returns the local address of the SPIPE's endpoint in @arg addr.
+ * @return 0 for success; -1 for failure. If a failure occurs, further
+ * error information is available from ACE_OS::last_error().
+ */
+ int get_local_addr (ACE_SPIPE_Addr &) const;
+
+ /**
+ * Disable signal @arg signum.
+ * @note This reimplements the inherited method from
+ * ACE_IPC_SAP. Since the signal actions do not make any sense on
+ * Windows, this method intercepts the call and NOPs it. On non-Windows,
+ * it is passed through to ACE_IPC_SAP::disable().
+ */
+ int disable (int signum) const ;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Ensure that this class is an abstract base class
+ ACE_SPIPE (void);
+
+ /// Our local address.
+ ACE_SPIPE_Addr local_addr_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SPIPE_H */
diff --git a/ace/IPC/SPIPE.i b/ace/IPC/SPIPE.i
new file mode 100644
index 00000000000..fd205ab76df
--- /dev/null
+++ b/ace/IPC/SPIPE.i
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SPIPE.i
+
+ASYS_INLINE int
+ACE_SPIPE::disable (int signum) const
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (signum) ;
+ return 0 ;
+#else /* ACE_WIN32 */
+ return ACE_IPC_SAP::disable (signum) ;
+#endif /* ACE_WIN32 */
+}
+
diff --git a/ace/IPC/SPIPE_Acceptor.cpp b/ace/IPC/SPIPE_Acceptor.cpp
new file mode 100644
index 00000000000..ace2ceabbc5
--- /dev/null
+++ b/ace/IPC/SPIPE_Acceptor.cpp
@@ -0,0 +1,271 @@
+// SPIPE_Acceptor.cpp
+// $Id$
+
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, SPIPE_Acceptor, "$Id$")
+
+ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (void)
+#if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ : pipe_handle_ (ACE_INVALID_HANDLE)
+#endif /* ACE_WIN32 */
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
+}
+
+int
+ACE_SPIPE_Acceptor::remove (void)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::remove");
+#if defined (ACE_HAS_STREAM_PIPES)
+ int result = this->close ();
+
+ // Remove the underlying file.
+ return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1
+ || result == -1 ? -1 : 0;
+#else
+ this->close ();
+ return 0;
+#endif
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_SPIPE_Acceptor)
+
+void
+ACE_SPIPE_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::dump");
+}
+
+// General purpose routine for performing server ACE_SPIPE creation.
+
+int
+ACE_SPIPE_Acceptor::open (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr,
+ int perms)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::open");
+ ACE_UNUSED_ARG (reuse_addr);
+
+ this->local_addr_ = local_sap;
+ this->set_handle (ACE_INVALID_HANDLE);
+
+ return this->create_new_instance (perms);
+}
+
+int
+ACE_SPIPE_Acceptor::create_new_instance (int perms)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_HANDLE spipe[2];
+ char module[] = "connld";
+
+ ACE_HANDLE handle = ACE_OS::creat (this->local_addr_.get_path_name (),
+ perms);
+ if (handle == ACE_INVALID_HANDLE)
+ return -1;
+ else if (ACE_OS::close (handle) == -1)
+ return -1;
+ else if (ACE_OS::pipe (spipe) == -1)
+ return -1;
+ else if (ACE_OS::ioctl (spipe[0],
+ I_PUSH,
+ module) == -1)
+ return -1;
+ else if (ACE_OS::fattach (spipe[0],
+ this->local_addr_.get_path_name ()) == -1)
+ return -1;
+
+ this->set_handle (spipe[1]);
+ return 0;
+
+#elif (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+
+ // Create a new instance of the Named Pipe (WIN32). A new instance
+ // of the named pipe must be created for every client process. If
+ // an instance of the named pipe that is already connected to a
+ // client process is reused with a new client process,
+ // ::ConnectNamedPipe () would fail.
+
+ ACE_UNUSED_ARG (perms);
+ ACE_TRACE ("ACE_SPIPE_Acceptor::create_new_instance");
+ int status;
+
+ // Create a new instance of the named pipe
+ this->pipe_handle_ =
+#if defined (ACE_USES_WCHAR)
+ ::CreateNamedPipeW (
+#else /* ACE_USES_WCHAR */
+ ::CreateNamedPipeA (
+#endif /* ACE_USES_WCHAR */
+ this->local_addr_.get_path_name (),
+ PIPE_ACCESS_DUPLEX
+ | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE
+ | PIPE_READMODE_MESSAGE,
+ PIPE_UNLIMITED_INSTANCES,
+ 1024 * 10,
+ 1024 * 10,
+ ACE_DEFAULT_TIMEOUT,
+ NULL);
+
+
+ if (this->pipe_handle_ == ACE_INVALID_HANDLE)
+ return -1;
+ else
+ {
+ // Start the Connect (analogous to listen () for a socket). Completion
+ // is noted by the event being signalled. If a client connects
+ // before this call, the error status will be ERROR_PIPE_CONNECTED, in
+ // which case that fact is remembered via already_connected_ and noted
+ // when the user calls accept ().
+ // Else the error status should be ERROR_IO_PENDING and the OS will
+ // signal the event when it's done.
+ this->already_connected_ = 0;
+ this->set_handle (this->event_.handle ());
+ this->overlapped_.hEvent = this->event_.handle ();
+ this->event_.reset ();
+
+ BOOL result = ::ConnectNamedPipe (this->pipe_handle_,
+ &this->overlapped_);
+ ACE_ASSERT (result == FALSE);
+ ACE_UNUSED_ARG (result);
+
+ status = ::GetLastError ();
+ if (status == ERROR_PIPE_CONNECTED)
+ this->already_connected_ = 1;
+ else if (status != ERROR_IO_PENDING)
+ this->close (); // Sets handle to ACE_INVALID_HANDLE
+ }
+ return (this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0);
+#else
+ ACE_UNUSED_ARG (perms);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+int
+ACE_SPIPE_Acceptor::close (void)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::close");
+
+#if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ // Substitute the pipe handle back in so it's closed properly.
+ this->set_handle (this->pipe_handle_);
+ this->pipe_handle_ = ACE_INVALID_HANDLE;
+#endif /* ACE_WIN32 */
+
+ // This behavior is shared by UNIX and Win32...
+ int result = this->ACE_SPIPE::close ();
+ this->set_handle (ACE_INVALID_HANDLE);
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_OS::fdetach (this->local_addr_.get_path_name ());
+#endif /* ACE_HAS_STREAM_PIPES */
+ return result;
+}
+
+ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr,
+ int perms)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
+
+ if (this->open (local_sap, reuse_addr, perms) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SPIPE_Acceptor")));
+}
+
+// General purpose routine for accepting new connections.
+
+int
+ACE_SPIPE_Acceptor::accept (ACE_SPIPE_Stream &new_io,
+ ACE_SPIPE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle)
+{
+ ACE_TRACE ("ACE_SPIPE_Acceptor::accept");
+ ACE_UNUSED_ARG (reset_new_handle);
+
+#if defined (ACE_HAS_STREAM_PIPES)
+ strrecvfd r_handle;
+
+ // Note that if THIS->MILLI_SECOND_DELAY == -1 we block on
+ // ACE_OS::ioctl (). Otherwise, we will wait for the desired number
+ // of milli seconds using ACE_OS::poll.
+
+ if (timeout != 0 &&
+ ACE::handle_timed_accept (this->get_handle (),
+ timeout,
+ restart) == -1)
+ return -1;
+ else if (ACE_OS::ioctl (this->get_handle (),
+ I_RECVFD,
+ &r_handle) == -1)
+ return -1;
+
+ new_io.set_handle (r_handle.fd);
+ new_io.local_addr_ = this->local_addr_;
+ new_io.remote_addr_.set_size (sizeof r_handle.gid + sizeof r_handle.uid);
+ new_io.remote_addr_.group_id (r_handle.gid);
+ new_io.remote_addr_.user_id (r_handle.uid);
+
+ // This is for compatibility with ACE_SOCK_Acceptor and
+ // ACE_TLI_Acceptor.
+ if (remote_addr != 0)
+ *remote_addr = new_io.remote_addr_;
+
+ return 0;
+#elif (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ ACE_UNUSED_ARG (restart);
+ ACE_UNUSED_ARG (remote_addr);
+
+ // Check to see if we have a valid pipe
+ if (this->pipe_handle_ == ACE_INVALID_HANDLE)
+ return -1;
+
+ // open () started the Connect in asynchronous mode. Wait for the event
+ // in the OVERLAPPED structure to be signalled, then grab the status.
+ if (this->already_connected_ == 0)
+ {
+ if (timeout != 0)
+ {
+ ACE_Time_Value abstime (ACE_OS::gettimeofday () + *timeout);
+ if (this->event_.wait (&abstime) == -1)
+ return -1;
+ }
+ else
+ if (this->event_.wait () == -1)
+ return -1;
+
+ // Should be here with the ConnectNamedPipe operation complete.
+ // Steal the already_connected_ flag to record the results.
+ DWORD unused;
+ this->already_connected_ = ::GetOverlappedResult (this->pipe_handle_,
+ &this->overlapped_,
+ &unused,
+ FALSE);
+ }
+
+ if (this->already_connected_)
+ {
+ new_io.set_handle (this->pipe_handle_);
+ this->pipe_handle_ = ACE_INVALID_HANDLE;
+ new_io.local_addr_ = this->local_addr_;
+
+ // Create a new instance of the pipe for the next connection.
+ this->create_new_instance ();
+ return 0;
+ }
+ return -1;
+#else
+ ACE_UNUSED_ARG (restart);
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (remote_addr);
+ ACE_UNUSED_ARG (new_io);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
diff --git a/ace/IPC/SPIPE_Acceptor.h b/ace/IPC/SPIPE_Acceptor.h
new file mode 100644
index 00000000000..cb2b536f736
--- /dev/null
+++ b/ace/IPC/SPIPE_Acceptor.h
@@ -0,0 +1,101 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt and Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_SPIPE_ACCEPTOR_H
+#define ACE_SPIPE_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/SPIPE_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_WIN32)
+#include "ace/Synch.h"
+#endif /* ACE_WIN32 */
+
+/**
+ * @class ACE_SPIPE_Acceptor
+ *
+ * @brief Defines the format and interface for the listener side of the
+ * ACE_SPIPE_Stream.
+ */
+class ACE_Export ACE_SPIPE_Acceptor : public ACE_SPIPE
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SPIPE_Acceptor (void);
+
+ /// Initiate a passive-mode STREAM pipe listener.
+ ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Initiate a passive-mode STREAM pipe listener. Returns 0 on
+ /// success and -1 on failure.
+ int open (const ACE_SPIPE_Addr &local_sap,
+ int reuse_addr = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Close down the passive-mode STREAM pipe listener.
+ int close (void);
+
+ /// Remove the underlying mounted pipe from the file system.
+ int remove (void);
+
+ // = Passive connection acceptance method.
+ /**
+ * Accept a new data transfer connection. A <timeout> of 0 means
+ * block forever, a <timeout> of {0, 0} means poll. <restart> == 1
+ * means "restart if interrupted."
+ */
+ int accept (ACE_SPIPE_Stream &ipc_sap_spipe,
+ ACE_SPIPE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0);
+
+ // = Meta-type info
+ typedef ACE_SPIPE_Addr PEER_ADDR;
+ typedef ACE_SPIPE_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Create a new instance of an SPIPE.
+ int create_new_instance (int perms = 0);
+
+#if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ // On Windows, the handle maintained in the ACE_IPC_SAP class is the
+ // event handle from event_. The pipe handle is useless for telling
+ // when a pipe connect is done/ready, and it changes on each pipe
+ // acceptance, quite unlike other acceptor-type classes in ACE.
+ // This allows the get_handle()-obtained handle to be used for
+ // registering with the reactor (albeit for signal, not input)
+ // to tell when a pipe accept is done.
+ ACE_OVERLAPPED overlapped_;
+ ACE_Manual_Event event_;
+ ACE_HANDLE pipe_handle_;
+ int already_connected_;
+#endif /* ACE_WIN32 */
+
+};
+
+#include "ace/post.h"
+#endif /* ACE_SPIPE_ACCEPTOR_H */
diff --git a/ace/IPC/SPIPE_Addr.cpp b/ace/IPC/SPIPE_Addr.cpp
new file mode 100644
index 00000000000..1d388f670ce
--- /dev/null
+++ b/ace/IPC/SPIPE_Addr.cpp
@@ -0,0 +1,142 @@
+// SPIPE_Addr.cpp
+// $Id$
+
+#include "ace/SPIPE_Addr.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SPIPE_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SPIPE_Addr, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Addr)
+
+void
+ACE_SPIPE_Addr::dump (void) const
+{
+}
+
+// Set a pointer to the address.
+void
+ACE_SPIPE_Addr::set_addr (void *addr, int len)
+{
+ ACE_TRACE ("ACE_SPIPE_Addr::set_addr");
+
+ this->ACE_Addr::base_set (AF_SPIPE, len);
+ ACE_OS::memcpy ((void *) &this->SPIPE_addr_,
+ (void *) addr,
+ len);
+}
+
+// Do nothing constructor.
+
+ACE_SPIPE_Addr::ACE_SPIPE_Addr (void)
+ : ACE_Addr (AF_SPIPE, sizeof this->SPIPE_addr_)
+{
+ (void) ACE_OS::memset ((void *) &this->SPIPE_addr_,
+ 0,
+ sizeof this->SPIPE_addr_);
+}
+
+// Transform the string into the current addressing format.
+
+int
+ACE_SPIPE_Addr::string_to_addr (const ACE_TCHAR *addr)
+{
+ return this->set (addr);
+}
+
+int
+ACE_SPIPE_Addr::set (const ACE_SPIPE_Addr &sa)
+{
+ this->base_set (sa.get_type (), sa.get_size ());
+
+ if (sa.get_type () == AF_ANY)
+ (void) ACE_OS::memset ((void *) &this->SPIPE_addr_,
+ 0,
+ sizeof this->SPIPE_addr_);
+ else
+ (void) ACE_OS::memcpy ((void *) &this->SPIPE_addr_, (void *)
+ &sa.SPIPE_addr_,
+ sa.get_size ());
+ return 0;
+}
+
+// Copy constructor.
+
+ACE_SPIPE_Addr::ACE_SPIPE_Addr (const ACE_SPIPE_Addr &sa)
+ : ACE_Addr (AF_SPIPE, sizeof this->SPIPE_addr_)
+{
+ this->set (sa);
+}
+
+int
+ACE_SPIPE_Addr::set (const ACE_TCHAR *addr,
+ gid_t gid,
+ uid_t uid)
+{
+ int len = sizeof (this->SPIPE_addr_.uid_);
+ len += sizeof (this->SPIPE_addr_.gid_);
+
+#if defined (ACE_WIN32)
+ const ACE_TCHAR *colonp = ACE_OS::strchr (addr, ':');
+ ACE_TCHAR temp[BUFSIZ];
+
+ if (colonp == 0) // Assume it's a local name.
+ {
+ ACE_OS::strcpy (temp, ACE_LIB_TEXT ( "\\\\.\\pipe\\"));
+ ACE_OS::strcat (temp, addr);
+ }
+ else
+ {
+
+ if (ACE_OS::strncmp (addr,
+ ACE_LIB_TEXT ("localhost"),
+ ACE_OS::strlen ("localhost")) == 0)
+ // change "localhost" to "."
+ ACE_OS::strcpy (temp, ACE_LIB_TEXT ("\\\\."));
+ else
+ {
+ ACE_OS::strcpy (temp, ACE_LIB_TEXT ("\\\\"));
+
+ ACE_TCHAR *t;
+
+ // We need to allocate a duplicate so that we can write a
+ // NUL character into it.
+ ACE_ALLOCATOR_RETURN (t, ACE_OS::strdup (addr), -1);
+
+ t[colonp - addr] = ACE_LIB_TEXT ('\0');
+ ACE_OS::strcpy (temp, t);
+
+ ACE_OS::free (t);
+ }
+
+ ACE_OS::strcat (temp, ACE_LIB_TEXT ("\\pipe\\"));
+ ACE_OS::strcat (temp, colonp + 1);
+ }
+ this->ACE_Addr::base_set (AF_SPIPE,
+ ACE_OS::strlen (temp) + len);
+
+ ACE_OS::strcpy (this->SPIPE_addr_.rendezvous_, temp);
+#else
+ this->ACE_Addr::base_set (AF_SPIPE,
+ ACE_OS::strlen (addr) + 1 + len);
+ ACE_OS::strsncpy (this->SPIPE_addr_.rendezvous_,
+ addr,
+ sizeof this->SPIPE_addr_.rendezvous_);
+#endif /* ACE_WIN32 */
+ this->SPIPE_addr_.gid_ = gid == 0 ? ACE_OS::getgid () : gid;
+ this->SPIPE_addr_.uid_ = uid == 0 ? ACE_OS::getuid () : uid;
+ return 0;
+}
+
+// Create a ACE_Addr from a ACE_SPIPE pathname.
+
+ACE_SPIPE_Addr::ACE_SPIPE_Addr (const ACE_TCHAR *addr,
+ gid_t gid,
+ uid_t uid)
+ : ACE_Addr (AF_SPIPE, sizeof this->SPIPE_addr_)
+{
+ this->set (addr, gid, uid);
+}
+
diff --git a/ace/IPC/SPIPE_Addr.h b/ace/IPC/SPIPE_Addr.h
new file mode 100644
index 00000000000..c4878d5d374
--- /dev/null
+++ b/ace/IPC/SPIPE_Addr.h
@@ -0,0 +1,113 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE_Addr.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SPIPE_ADDR_H
+#define ACE_SPIPE_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+
+/**
+ * @class ACE_SPIPE_Addr
+ *
+ * @brief Defines the SVR4 STREAM pipe address family address format.
+ */
+class ACE_Export ACE_SPIPE_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_SPIPE_Addr (void);
+
+ /// Copy constructor.
+ ACE_SPIPE_Addr (const ACE_SPIPE_Addr &sa);
+
+ /// Create a ACE_SPIPE_Addr from a rendezvous point in the file
+ /// system.
+ ACE_SPIPE_Addr (const ACE_TCHAR *rendezvous_point, gid_t = 0, uid_t = 0);
+
+ /// Acts like a copy constructor...
+ int set (const ACE_SPIPE_Addr &sa);
+
+ /// Create a ACE_SPIPE_Addr from a rendezvous point in the file
+ /// system.
+ int set (const ACE_TCHAR *rendezvous_point, gid_t = 0, uid_t = 0);
+
+ /// Return a pointer to the address.
+ virtual void *get_addr (void) const;
+
+ /// Set a pointer to the underlying network address.
+ virtual void set_addr (void *addr, int len);
+
+ /// Transform the current address into string format.
+ virtual int addr_to_string (ACE_TCHAR *addr, size_t) const;
+
+ /// Transform the string into the current addressing format.
+ virtual int string_to_addr (const ACE_TCHAR *addr);
+
+ // = Equality/inequality tests
+ /// Check for equality.
+ int operator == (const ACE_SPIPE_Addr &SAP) const;
+
+ /// Check for inequality
+ int operator != (const ACE_SPIPE_Addr &SAP) const;
+
+ // = SPIPE-specific address operations
+ /// Pathname of rendezvous point in file system.
+ const ACE_TCHAR *get_path_name (void) const;
+
+ /// Get user id.
+ /// Set user id.
+ uid_t user_id (void) const;
+ void user_id (uid_t uid);
+
+ /// Set group ids.
+ /// Get group ids.
+ void group_id (gid_t gid);
+ gid_t group_id (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Contains security attributes.
+ struct SPIPE_Addr
+ {
+ gid_t gid_;
+ // Group id.
+
+ uid_t uid_;
+ // User id.
+
+ ACE_TCHAR rendezvous_[MAXNAMLEN + 1];
+ // Pathname in the file system.
+
+ } SPIPE_addr_;
+ // Contents of an SPIPE address.
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/SPIPE_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SPIPE_ADDR_H */
diff --git a/ace/IPC/SPIPE_Addr.i b/ace/IPC/SPIPE_Addr.i
new file mode 100644
index 00000000000..e6af565b53b
--- /dev/null
+++ b/ace/IPC/SPIPE_Addr.i
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SPIPE_Addr.i
+
+#include "ace/SString.h"
+
+// Transform the current address into string format.
+
+ACE_INLINE int
+ACE_SPIPE_Addr::addr_to_string (ACE_TCHAR *s, size_t len) const
+{
+ ACE_OS::strsncpy (s,
+ this->SPIPE_addr_.rendezvous_,
+ len);
+ return 0;
+}
+
+// Return the address.
+
+ACE_INLINE void *
+ACE_SPIPE_Addr::get_addr (void) const
+{
+ return (void *) &this->SPIPE_addr_;
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE int
+ACE_SPIPE_Addr::operator == (const ACE_SPIPE_Addr &sap) const
+{
+ return ACE_OS::strcmp (this->SPIPE_addr_.rendezvous_,
+ sap.SPIPE_addr_.rendezvous_ ) == 0;
+}
+
+// Compare two addresses for inequality.
+
+ACE_INLINE int
+ACE_SPIPE_Addr::operator != (const ACE_SPIPE_Addr &sap) const
+{
+ return !((*this) == sap); // This is lazy, of course... ;-)
+}
+
+// Return the path name used for the rendezvous point.
+
+ACE_INLINE const ACE_TCHAR *
+ACE_SPIPE_Addr::get_path_name (void) const
+{
+ return this->SPIPE_addr_.rendezvous_;
+}
+
+ACE_INLINE uid_t
+ACE_SPIPE_Addr::user_id (void) const
+{
+ return this->SPIPE_addr_.uid_;
+}
+
+ACE_INLINE void
+ACE_SPIPE_Addr::user_id (uid_t uid)
+{
+ this->SPIPE_addr_.uid_ = uid;
+}
+
+ACE_INLINE gid_t
+ACE_SPIPE_Addr::group_id (void) const
+{
+ return this->SPIPE_addr_.gid_;
+}
+
+ACE_INLINE void
+ACE_SPIPE_Addr::group_id (gid_t gid)
+{
+ this->SPIPE_addr_.gid_ = gid;
+}
diff --git a/ace/IPC/SPIPE_Connector.cpp b/ace/IPC/SPIPE_Connector.cpp
new file mode 100644
index 00000000000..a9006ef9f5a
--- /dev/null
+++ b/ace/IPC/SPIPE_Connector.cpp
@@ -0,0 +1,76 @@
+// SPIPE_Connector.cpp
+// $Id$
+
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE_Connector.i"
+#endif
+
+ACE_RCSID(ace, SPIPE_Connector, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Connector)
+
+// Creates a Local ACE_SPIPE.
+
+ACE_SPIPE_Connector::ACE_SPIPE_Connector (ACE_SPIPE_Stream &new_io,
+ const ACE_SPIPE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr & local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::ACE_SPIPE_Connector");
+ if (this->connect (new_io, remote_sap, timeout, local_sap,
+ reuse_addr, flags, perms) == -1
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("address %s, %p\n"),
+ remote_sap.get_path_name (), ACE_LIB_TEXT ("ACE_SPIPE_Connector")));
+}
+
+void
+ACE_SPIPE_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::dump");
+}
+
+ACE_SPIPE_Connector::ACE_SPIPE_Connector (void)
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::ACE_SPIPE_Connector");
+}
+
+int
+ACE_SPIPE_Connector::connect (ACE_SPIPE_Stream &new_io,
+ const ACE_SPIPE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr & /* local_sap */,
+ int /* reuse_addr */,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_SPIPE_Connector::connect");
+
+ // Make darn sure that the O_CREAT flag is not set!
+#if ! defined (ACE_PSOS_DIAB_MIPS)
+ ACE_CLR_BITS (flags, O_CREAT);
+# endif /* !ACE_PSOS_DIAB_MIPS */
+ ACE_HANDLE handle = ACE_Handle_Ops::handle_timed_open (timeout,
+ remote_sap.get_path_name (),
+ flags, perms);
+ new_io.set_handle (handle);
+ new_io.remote_addr_ = remote_sap; // class copy.
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+ DWORD pipe_mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+
+ // Set named pipe mode and buffering characteristics.
+ if (handle != ACE_INVALID_HANDLE)
+ return ::SetNamedPipeHandleState (handle,
+ &pipe_mode,
+ NULL,
+ NULL);
+#endif
+ return handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
diff --git a/ace/IPC/SPIPE_Connector.h b/ace/IPC/SPIPE_Connector.h
new file mode 100644
index 00000000000..6e400c32c40
--- /dev/null
+++ b/ace/IPC/SPIPE_Connector.h
@@ -0,0 +1,105 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu> and Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SPIPE_CONNECTOR_H
+#define ACE_SPIPE_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/SPIPE_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SPIPE_Connector
+ *
+ * @brief Defines an active connection factory for the STREAM pipe
+ * wrappers.
+ */
+class ACE_Export ACE_SPIPE_Connector
+{
+public:
+ // = Initialization method.
+ /// Default constructor.
+ ACE_SPIPE_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ ACE_SPIPE_Connector (ACE_SPIPE_Stream &new_io,
+ const ACE_SPIPE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ int connect (ACE_SPIPE_Stream &new_io,
+ const ACE_SPIPE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ // = Meta-type info
+ typedef ACE_SPIPE_Addr PEER_ADDR;
+ typedef ACE_SPIPE_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE_Connector.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SPIPE_CONNECTOR_H */
diff --git a/ace/IPC/SPIPE_Connector.i b/ace/IPC/SPIPE_Connector.i
new file mode 100644
index 00000000000..9ce4c1a7855
--- /dev/null
+++ b/ace/IPC/SPIPE_Connector.i
@@ -0,0 +1,13 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SPIPE_Connector.i
+
+ASYS_INLINE int
+ACE_SPIPE_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_UNUSED_ARG (handle);
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
+
diff --git a/ace/IPC/SPIPE_Stream.cpp b/ace/IPC/SPIPE_Stream.cpp
new file mode 100644
index 00000000000..9488d8dcdc0
--- /dev/null
+++ b/ace/IPC/SPIPE_Stream.cpp
@@ -0,0 +1,98 @@
+// SPIPE_Stream.cpp
+// $Id$
+
+#include "ace/SPIPE_Stream.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE_Stream.i"
+#endif
+
+ACE_RCSID(ace, SPIPE_Stream, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Stream)
+
+void
+ACE_SPIPE_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::dump");
+}
+
+// Simple-minded do nothing constructor.
+
+ACE_SPIPE_Stream::ACE_SPIPE_Stream (void)
+{
+ // ACE_TRACE ("ACE_SPIPE_Stream::ACE_SPIPE_Stream");
+}
+
+// Send N char *ptrs and int lengths. Note that the char *'s precede
+// the ints (basically, an varargs version of writev). The count N is
+// the *total* number of trailing arguments, *not* a couple of the
+// number of tuple pairs!
+
+ssize_t
+ACE_SPIPE_Stream::send (size_t n, ...) const
+{
+ // ACE_TRACE ("ACE_SPIPE_Stream::send");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::writev (this->get_handle (), iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// This is basically an interface to ACE_OS::readv, that doesn't use
+// the struct iovec explicitly. The ... can be passed as an arbitrary
+// number of (char *ptr, int len) tuples. However, the count N is the
+// *total* number of trailing arguments, *not* a couple of the number
+// of tuple pairs!
+
+ssize_t
+ACE_SPIPE_Stream::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, int);
+ }
+
+ ssize_t result = ACE_OS::readv (this->get_handle (), iovp, total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
diff --git a/ace/IPC/SPIPE_Stream.h b/ace/IPC/SPIPE_Stream.h
new file mode 100644
index 00000000000..1bbed754227
--- /dev/null
+++ b/ace/IPC/SPIPE_Stream.h
@@ -0,0 +1,147 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SPIPE_Stream.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SPIPE_STREAM_H
+#define ACE_SPIPE_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/SPIPE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SPIPE_Addr.h"
+
+/**
+ * @class ACE_SPIPE_Stream
+ *
+ * @brief Define an ACE_SPIPE_Stream.
+ */
+class ACE_Export ACE_SPIPE_Stream : public ACE_SPIPE
+{
+public:
+ friend class ACE_SPIPE_Acceptor;
+ friend class ACE_SPIPE_Connector;
+
+ // = Initialization method.
+ /// Default constructor.
+ ACE_SPIPE_Stream (void);
+
+ /// Obtain the address of whom we are connected with.
+ int get_remote_addr (ACE_SPIPE_Addr &remote_sap) const;
+
+ /// Send an open FD to another process.
+ int send_handle (ACE_HANDLE handle) const;
+
+ /// Recv an open FD from another process.
+ int recv_handle (ACE_HANDLE &handle) const;
+
+ /// Recv an open FD from another process.
+ int recv_handle (strrecvfd &recvfd) const;
+
+ /// Send n bytes, keep trying until n are sent.
+ ssize_t send_n (const void *buf, size_t n) const;
+
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t recv_n (void *buf, size_t n) const;
+
+ /// Send bytes via STREAM pipes using "band" mode.
+ ssize_t send (const void *buf, size_t n) const;
+
+ /// Recv bytes via STREAM pipes using "band" mode.
+ ssize_t recv (void *buf, size_t n) const;
+
+ /// Send <cntl> and <data> via STREAM pipes.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int flags = 0) const;
+
+ /// Recv <cntl> and <data> via STREAM pipes.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *flags) const;
+
+ /// Send bytes via STREAM pipes using "band" mode.
+ ssize_t send (const ACE_Str_Buf *cntl,
+ const ACE_Str_Buf *data,
+ int band,
+ int flags) const;
+
+ /// Recv bytes via STREAM pipes using "band" mode.
+ ssize_t recv (ACE_Str_Buf *cntl,
+ ACE_Str_Buf *data,
+ int *band,
+ int *flags) const;
+
+ /// Send iovecs via <::writev>.
+ ssize_t send (const iovec iov[], size_t n) const;
+
+ /// Recv iovecs via <::readv>.
+ ssize_t recv (iovec iov[], size_t n) const;
+
+ /**
+ * Send N char *ptrs and int lengths. Note that the char *'s
+ * precede the ints (basically, an varargs version of writev). The
+ * count N is the *total* number of trailing arguments, *not* a
+ * couple of the number of tuple pairs!
+ */
+ ssize_t send (size_t n, ...) const;
+
+ /**
+ * This is an interface to ::readv, that doesn't use the struct
+ * iovec explicitly. The ... can be passed as an arbitrary number
+ * of (char *ptr, int len) tuples. However, the count N is the
+ * *total* number of trailing arguments, *not* a couple of the
+ * number of tuple pairs!
+ */
+ ssize_t recv (size_t n, ...) const;
+
+ /// Send <n> bytes via Win32 WriteFile using overlapped I/O.
+ ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const;
+
+ /// Recv <n> bytes via Win32 ReadFile using overlapped I/O.
+ ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an <iovec> of size <n> to the stream.
+ ssize_t sendv (const iovec iov[],
+ size_t n) const;
+
+ /// Send an <iovec> of size <n> to the stream. Will block until all
+ /// bytes are sent or an error occurs.
+ ssize_t sendv_n (const iovec iov[],
+ size_t n) const;
+
+ /// Receive an <iovec> of size <n> to the stream.
+ ssize_t recvv_n (iovec iov[],
+ size_t n) const;
+
+ // = Meta-type info
+ typedef ACE_SPIPE_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ ACE_SPIPE_Addr remote_addr_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SPIPE_Stream.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SPIPE_STREAM_H */
diff --git a/ace/IPC/SPIPE_Stream.i b/ace/IPC/SPIPE_Stream.i
new file mode 100644
index 00000000000..4733a628815
--- /dev/null
+++ b/ace/IPC/SPIPE_Stream.i
@@ -0,0 +1,198 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SPIPE_Stream.i
+
+// Create an ACE_SPIPE_Stream.
+
+ASYS_INLINE int
+ACE_SPIPE_Stream::get_remote_addr (ACE_SPIPE_Addr &remote_sap) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::get_remote_addr");
+ remote_sap = this->remote_addr_;
+ return 0;
+}
+
+// Send exactly N bytes from BUF to this socket. Keeping trying until
+// this many bytes are sent.
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send_n (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send_n");
+ return ACE::write_n (this->get_handle (), buf, n);
+}
+
+// Receive exactly N bytes from this socket into BUF. Keep trying
+// until this many bytes are received.
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv_n (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv_n");
+ return ACE::read_n (this->get_handle (), buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send (const void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::write (this->get_handle (), (const char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv (void *buf, size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ return ACE_OS::read (this->get_handle (), (char *) buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send (const iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::writev (this->get_handle (), iov, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv (iovec iov[], size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ return ACE_OS::readv (this->get_handle (), iov, n);
+}
+
+// This routine sends an open file descriptor to this socket.
+
+ASYS_INLINE int
+ACE_SPIPE_Stream::send_handle (ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send_handle");
+#if defined (ACE_HAS_STREAM_PIPES)
+ return ACE_OS::ioctl (this->get_handle (), I_SENDFD, (void *) handle);
+#else
+ handle = handle;
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+// This file receives an open file descriptor from this socket.
+
+ASYS_INLINE int
+ACE_SPIPE_Stream::recv_handle (ACE_HANDLE &handle) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv_handle");
+#if defined (ACE_HAS_STREAM_PIPES)
+ strrecvfd recvfd;
+
+ if (ACE_OS::ioctl (this->get_handle (), I_RECVFD, (void *) &recvfd) == -1)
+ return -1;
+ else
+ {
+ handle = recvfd.fd;
+ return 0;
+ }
+#else
+ handle = handle;
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+// This file receives an open file descriptor from this socket and
+// also passes back the information about the address...
+
+ASYS_INLINE int
+ACE_SPIPE_Stream::recv_handle (strrecvfd &recvfd) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv_handle");
+#if defined (ACE_HAS_STREAM_PIPES)
+ return ACE_OS::ioctl (this->get_handle (), I_RECVFD, (void *) &recvfd);
+#else
+ ACE_UNUSED_ARG (recvfd);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::send (const void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::send");
+ return ACE_OS::write (this->get_handle (),
+ (const char *) buf, n,
+ overlapped);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recv (void *buf, size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recv");
+ return ACE_OS::read (this->get_handle (),
+ (char *) buf, n,
+ overlapped);
+}
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::sendv_n (const iovec iov[],
+ size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::sendv_n");
+ return ACE::writev_n (this->get_handle (),
+ iov,
+ n);
+}
+
+// Recv an n byte message from the Stream.
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::recvv_n (iovec iov[],
+ size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::recvv_n");
+ // @@ Carlos, can you please update this to call the
+ // new ACE::recvv_n() method that you write?
+ return ACE_OS::readv (this->get_handle (),
+ iov,
+ n);
+}
+
+// Send an <iovec> of size <n> to the Stream.
+
+ASYS_INLINE ssize_t
+ACE_SPIPE_Stream::sendv (const iovec iov[],
+ size_t n) const
+{
+ ACE_TRACE ("ACE_SPIPE_Stream::sendv");
+ return ACE_OS::writev (this->get_handle (),
+ iov,
+ n);
+}
+
diff --git a/ace/IPC/SV_Message.cpp b/ace/IPC/SV_Message.cpp
new file mode 100644
index 00000000000..fef83458651
--- /dev/null
+++ b/ace/IPC/SV_Message.cpp
@@ -0,0 +1,19 @@
+// SV_Message.cpp
+// $Id$
+
+#include "ace/SV_Message.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Message.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Message, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message)
+
+void
+ACE_SV_Message::dump (void) const
+{
+ ACE_TRACE ("ACE_SV_Message::dump");
+}
+
diff --git a/ace/IPC/SV_Message.h b/ace/IPC/SV_Message.h
new file mode 100644
index 00000000000..b93d9e531e5
--- /dev/null
+++ b/ace/IPC/SV_Message.h
@@ -0,0 +1,56 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SV_Message.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SV_MESSAGE_H
+#define ACE_SV_MESSAGE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SV_Message
+ *
+ * @brief Defines the header file for the C++ wrapper for message queues.
+ */
+class ACE_Export ACE_SV_Message
+{
+public:
+ // = Initialization and termination methods.
+ ACE_SV_Message (long type = 0);
+ ~ACE_SV_Message (void);
+
+ // = Get/set the message type.
+ long type (void) const;
+ void type (long);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Type of the message.
+ long type_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Message.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SV_MESSAGE_H */
diff --git a/ace/IPC/SV_Message.i b/ace/IPC/SV_Message.i
new file mode 100644
index 00000000000..8c08e41d151
--- /dev/null
+++ b/ace/IPC/SV_Message.i
@@ -0,0 +1,31 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SV_Message.i
+
+ACE_INLINE
+ACE_SV_Message::ACE_SV_Message (long t)
+ : type_ (t)
+{
+ ACE_TRACE ("ACE_SV_Message::ACE_SV_Message");
+}
+
+ACE_INLINE
+ACE_SV_Message::~ACE_SV_Message (void)
+{
+ ACE_TRACE ("ACE_SV_Message::~ACE_SV_Message");
+}
+
+ACE_INLINE long
+ACE_SV_Message::type (void) const
+{
+ ACE_TRACE ("ACE_SV_Message::type");
+ return this->type_;
+}
+
+ACE_INLINE void
+ACE_SV_Message::type (long t)
+{
+ ACE_TRACE ("ACE_SV_Message::type");
+ this->type_ = t;
+}
diff --git a/ace/IPC/SV_Message_Queue.cpp b/ace/IPC/SV_Message_Queue.cpp
new file mode 100644
index 00000000000..d9f924e82eb
--- /dev/null
+++ b/ace/IPC/SV_Message_Queue.cpp
@@ -0,0 +1,39 @@
+// SV_Message_Queue.cpp
+// $Id$
+
+#include "ace/SV_Message_Queue.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Message_Queue.i"
+#endif
+
+ACE_RCSID(ace, SV_Message_Queue, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message_Queue)
+
+void
+ACE_SV_Message_Queue::dump (void) const
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::dump");
+}
+
+ACE_SV_Message_Queue::ACE_SV_Message_Queue (void)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::ACE_SV_Message_Queue");
+}
+
+ACE_SV_Message_Queue::~ACE_SV_Message_Queue (void)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::~ACE_SV_Message_Queue");
+}
+
+ACE_SV_Message_Queue::ACE_SV_Message_Queue (key_t external_id,
+ int create,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::ACE_SV_Message_Queue");
+ if (this->open (external_id, create, perms) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SV_Message_Queue::ACE_SV_Message_Queue")));
+}
diff --git a/ace/IPC/SV_Message_Queue.h b/ace/IPC/SV_Message_Queue.h
new file mode 100644
index 00000000000..20af5ad8cfa
--- /dev/null
+++ b/ace/IPC/SV_Message_Queue.h
@@ -0,0 +1,95 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SV_Message_Queue.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SV_MESSAGE_QUEUE_H
+#define ACE_SV_MESSAGE_QUEUE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SV_Message.h"
+
+/**
+ * @class ACE_SV_Message_Queue
+ *
+ * @brief Defines the header file for the C++ wrapper for System V IPC
+ * message queues.
+ */
+class ACE_Export ACE_SV_Message_Queue
+{
+public:
+ // = Useful symbolic constants.
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_OPEN = 0,
+ ACE_NOWAIT = IPC_NOWAIT
+ };
+
+ // = Initialization and termination methods.
+ /// Open a message queue using the <external_id>.
+ ACE_SV_Message_Queue (void);
+ ACE_SV_Message_Queue (key_t external_id,
+ int create = ACE_SV_Message_Queue::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ int open (key_t external_id,
+ int create = ACE_SV_Message_Queue::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ ~ACE_SV_Message_Queue (void);
+
+ /// Close down this instance of the message queue without removing it
+ /// from the system.
+ int close (void);
+
+ /// Close down and remove the message queue from the system.
+ int remove (void);
+
+
+ // = Message transfer methods.
+ int recv (ACE_SV_Message &mb,
+ int length,
+ long mtype = 0,
+ int mflags = 0);
+
+ int send (const ACE_SV_Message &mb,
+ int length,
+ int mflags = 0);
+
+ /// Access the underlying control operations.
+ int control (int option, void *arg = 0);
+
+ // = Get/set the underly internal id.
+ int get_id (void) const;
+ void set_id (int);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Returned from the underlying <msgget> system call.
+ int internal_id_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Message_Queue.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SV_MESSAGE_QUEUE_H */
diff --git a/ace/IPC/SV_Message_Queue.i b/ace/IPC/SV_Message_Queue.i
new file mode 100644
index 00000000000..65c092136f7
--- /dev/null
+++ b/ace/IPC/SV_Message_Queue.i
@@ -0,0 +1,78 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SV_Message_Queue.i
+
+#include "ace/SV_Message_Queue.h"
+
+// Open a message queue using the <external_id>.
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::open (key_t external_id, int create, int perms)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::open");
+ return this->internal_id_ = ACE_OS::msgget (external_id, create | perms);
+}
+
+// What does it mean to close a message queue?!
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::close (void)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::close");
+ this->internal_id_ = -1;
+ return 1;
+}
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::control (int option, void *arg)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::control");
+ return ACE_OS::msgctl (this->internal_id_, option,
+ (msqid_ds *) arg);
+}
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::remove (void)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::remove");
+ int result = this->control (IPC_RMID);
+ this->internal_id_ = -1;
+ return result;
+}
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::get_id (void) const
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::get_id");
+ return this->internal_id_;
+}
+
+ASYS_INLINE void
+ACE_SV_Message_Queue::set_id (int id)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::set_id");
+ this->internal_id_ = id;
+}
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::recv (ACE_SV_Message &mb,
+ int length,
+ long type,
+ int mflags)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::recv");
+ return ACE_OS::msgrcv (this->internal_id_, (void *) &mb,
+ length, type, mflags);
+}
+
+ASYS_INLINE int
+ACE_SV_Message_Queue::send (const ACE_SV_Message &mb,
+ int length,
+ int mflags)
+{
+ ACE_TRACE ("ACE_SV_Message_Queue::send");
+ return ACE_OS::msgsnd (this->internal_id_, (void *) &mb,
+ length, mflags);
+}
+
diff --git a/ace/IPC/SV_Semaphore_Complex.cpp b/ace/IPC/SV_Semaphore_Complex.cpp
new file mode 100644
index 00000000000..4c751da24cb
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Complex.cpp
@@ -0,0 +1,252 @@
+// SV_Semaphore_Complex.cpp
+// $Id$
+
+#include "ace/SV_Semaphore_Complex.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Semaphore_Complex.i"
+#endif
+
+ACE_RCSID(ace, SV_Semaphore_Complex, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Complex)
+
+void
+ACE_SV_Semaphore_Complex::dump (void) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::dump");
+}
+
+// initial value of process
+const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000;
+
+// Define the ACE_SV_Semaphore operation arrays for the semop() calls.
+sembuf ACE_SV_Semaphore_Complex::op_lock_[2] =
+{
+ {0, 0, 0}, // Wait for [0] (lock) to equal 0
+ {0, 1, SEM_UNDO}, // then increment [0] to 1 - this locks it.
+ // UNDO to release the lock if processes exit
+ // before explicitly unlocking.
+};
+
+sembuf ACE_SV_Semaphore_Complex::op_endcreate_[2] =
+{
+ {1, -1, SEM_UNDO}, // Decrement [1] (proc counter) with undo on
+ // exit, UNDO to adjust proc counter if
+ // process exits before explicitly calling close()
+ {0, -1, SEM_UNDO}, // the decrement [0] (lock) back to 0
+};
+
+sembuf ACE_SV_Semaphore_Complex::op_open_[1] =
+{
+ {1, -1, SEM_UNDO}, // Decrement [1] (proc counter) with undo on
+ // exit.
+};
+
+sembuf ACE_SV_Semaphore_Complex::op_close_[3] =
+{
+ {0, 0, 0}, // Wait for [0] (lock) to equal 0
+ {0, 1, SEM_UNDO}, // then increment [0] to 1 - this lock it
+ {1, 1, SEM_UNDO}, // then increment [1] (proc counter)
+};
+
+sembuf ACE_SV_Semaphore_Complex::op_unlock_[1] =
+{
+ {0, -1, SEM_UNDO}, // Decrement [0] (lock) back to 0
+};
+
+// Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1.
+
+int
+ACE_SV_Semaphore_Complex::open (key_t k,
+ int create,
+ int initial_value,
+ u_short nsems,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
+ if (k == IPC_PRIVATE)
+ return -1;
+
+ this->key_ = k;
+
+ // Must include a count for the 2 additional semaphores we use
+ // internally.
+ this->sem_number_ = nsems + 2;
+
+ if (create == ACE_SV_Semaphore_Complex::ACE_CREATE)
+ {
+ int result;
+
+ do
+ {
+ this->internal_id_ = ACE_OS::semget
+ (this->key_,
+ (u_short) 2 + nsems,
+ perms | ACE_SV_Semaphore_Complex::ACE_CREATE);
+
+ if (this->internal_id_ == -1)
+ return -1; // permission problem or tables full
+
+ // When the <ACE_SV_Semaphore_Complex> is created, we know
+ // that the value of all 3 members is 0. Get a lock on the
+ // <ACE_SV_Semaphore_Complex> by waiting for [0] to equal 0,
+ // then increment it.
+
+ // There is a race condition here. There is the possibility
+ // that between the <semget> above and the <semop> below,
+ // another process can call out <close> function which can
+ // remove the <ACE_SV_Semaphore> if that process is the last
+ // one using it. Therefor we handle the error condition of
+ // an invalid <ACE_SV_Semaphore> ID specifically below, and
+ // if it does happen, we just go back and create it again.
+ result = ACE_OS::semop (this->internal_id_,
+ &ACE_SV_Semaphore_Complex::op_lock_[0],
+ 2);
+ }
+ while (result == -1 && (errno == EINVAL || errno == EIDRM));
+
+ if (result == -1)
+ return -1;
+
+ // Get the value of the process counter. If it equals 0, then no
+ // one has initialized the ACE_SV_Semaphore yet.
+
+ int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1);
+
+ if (semval == -1)
+ return this->init ();
+ else if (semval == 0)
+ {
+ // We should initialize by doing a SETALL, but that would
+ // clear the adjust value that we set when we locked the
+ // ACE_SV_Semaphore above. Instead we do system calls to
+ // initialize [1], as well as all the nsems SV_Semaphores.
+
+ if (ACE_SV_Semaphore_Simple::control (SETVAL,
+ ACE_SV_Semaphore_Complex::BIGCOUNT_,
+ 1) == -1)
+ return -1;
+ else
+ for (int i = 0; i < nsems; i++)
+ if (this->control (SETVAL, initial_value, i) == -1)
+ return -1;
+ }
+
+ // Decrement the process counter and then release the lock.
+ return ACE_OS::semop (this->internal_id_,
+ &ACE_SV_Semaphore_Complex::op_endcreate_[0],
+ 2);
+ }
+ else
+ {
+ this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0);
+ if (this->internal_id_ == -1)
+ return -1; // doesn't exist or tables full
+
+ // Decrement the process counter. We don't need a lock to do this.
+ if (ACE_OS::semop (this->internal_id_,
+ &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0)
+ return this->init ();
+ return 0;
+ }
+}
+
+int
+ACE_SV_Semaphore_Complex::open (const char *name,
+ int flags,
+ int initial_value,
+ u_short nsems,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::open");
+ return this->open (ACE_SV_Semaphore_Simple::name_2_key (name),
+ flags, initial_value, nsems, perms);
+}
+
+// Close a ACE_SV_Semaphore. Unlike the remove above, this function
+// is for a process to call before it exits, when it is done with the
+// ACE_SV_Semaphore. We "decrement" the counter of processes using
+// the ACE_SV_Semaphore, and if this was the last one, we can remove
+// the ACE_SV_Semaphore.
+
+int
+ACE_SV_Semaphore_Complex::close (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::close");
+ int semval;
+
+ if (this->key_ == (key_t) - 1 || this->internal_id_ == -1)
+ return -1;
+
+ // The following semop() first gets a lock on the ACE_SV_Semaphore,
+ // then increments [1] - the process number.
+
+ if (ACE_OS::semop (this->internal_id_,
+ &ACE_SV_Semaphore_Complex::op_close_[0],
+ 3) == -1)
+ return -1;
+
+ // Now that we have a lock, read the value of the process counter to
+ // see if this is the last reference to the ACE_SV_Semaphore. There
+ // is a race condition here - see the comments in create ().
+
+ if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1)
+ return -1;
+
+ if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_)
+ return -1;
+ else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_)
+ return this->remove ();
+ else
+ {
+ int result = ACE_OS::semop (this->internal_id_,
+ &ACE_SV_Semaphore_Complex::op_unlock_[0], 1);
+ this->init ();
+ return result;
+ }
+}
+
+ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (key_t k,
+ int flags,
+ int initial_value,
+ u_short nsems,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
+ if (this->open (k, flags, initial_value, nsems, perms) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
+}
+
+ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (const char *name,
+ int flags,
+ int initial_value,
+ u_short nsems,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
+
+ key_t key;
+
+ if (name == 0)
+ key = ACE_DEFAULT_SEM_KEY;
+ else
+ key = this->name_2_key (name);
+
+ if (this->open (key, flags, initial_value, nsems, perms) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SV_Semaphore_Complex")));
+}
+
+ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex");
+ if (this->internal_id_ >= 0)
+ this->close ();
+}
+
+ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex");
+ this->init ();
+}
diff --git a/ace/IPC/SV_Semaphore_Complex.h b/ace/IPC/SV_Semaphore_Complex.h
new file mode 100644
index 00000000000..d89c855cc69
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Complex.h
@@ -0,0 +1,155 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SV_Semaphore_Complex.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SV_SEMAPHORE_COMPLEX_H
+#define ACE_SV_SEMAPHORE_COMPLEX_H
+#include "ace/pre.h"
+
+#include "ace/SV_Semaphore_Simple.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SV_Semaphore_Complex
+ *
+ * @brief This is a more complex semaphore wrapper that handles race
+ * conditions for initialization correctly...
+ *
+ * This code is a port to C++, inspired by: W. Richard Stevens
+ * from his book: UNIX Network Programming (Prentice Hall, ISBN
+ * 0-13-949876-1 - 1990). We provide a simpler and easier to
+ * understand interface to the System V Semaphore system calls.
+ * We create and use a 2 + n-member set for the requested
+ * <ACE_SV_Semaphore_Complex>. The first member, [0], is a
+ * counter used to know when all processes have finished with
+ * the <ACE_SV_Semaphore_Complex>. The counter is initialized
+ * to a large number, decremented on every create or open and
+ * incremented on every close. This way we can use the "adjust"
+ * feature provided by System V so that any process that exit's
+ * without calling <close> is accounted for. It doesn't help us
+ * if the last process does this (as we have no way of getting
+ * control to remove the <ACE_SV_Semaphore_Complex>) but it
+ * will work if any process other than the last does an exit
+ * (intentional or unintentional).
+ * The second member, [1], of the semaphore is used as a lock
+ * variable to avoid any race conditions in the <create> and
+ * <close> functions.
+ * The members beyond [1] are actual semaphore values in the
+ * array of semaphores, which may be sized by the user in the
+ * constructor.
+ */
+class ACE_Export ACE_SV_Semaphore_Complex : private ACE_SV_Semaphore_Simple
+{
+public:
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_OPEN = 0
+ };
+
+ // = Initialization and termination methods.
+ ACE_SV_Semaphore_Complex (void);
+ ACE_SV_Semaphore_Complex (key_t key,
+ int create = ACE_SV_Semaphore_Complex::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ ACE_SV_Semaphore_Complex (const char *name,
+ int create = ACE_SV_Semaphore_Complex::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ ~ACE_SV_Semaphore_Complex (void);
+
+ /// Open or create an array of SV_Semaphores. We return 0 if all is
+ /// OK, else -1.
+ int open (const char *name,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Open or create an array of SV_Semaphores. We return 0 if all is
+ /// OK, else -1.
+ int open (key_t key,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /**
+ * Close an ACE_SV_Semaphore. Unlike the <remove> method, this
+ * method is for a process to call before it exits, when it is done
+ * with the ACE_SV_Semaphore. We "decrement" the counter of
+ * processes using the ACE_SV_Semaphore, and if this was the last
+ * one, we can remove the ACE_SV_Semaphore.
+ */
+ int close (void);
+
+ // = Semaphore acquire and release methods.
+
+ /// Acquire the semaphore.
+ int acquire (u_short n = 0, int flags = 0) const;
+
+ /// Acquire a semaphore for reading.
+ int acquire_read (u_short n = 0, int flags = 0) const;
+
+ /// Acquire a semaphore for writing
+ int acquire_write (u_short n = 0, int flags = 0) const;
+
+ /// Try to acquire the semaphore.
+ int tryacquire (u_short n = 0, int flags = 0) const;
+
+ /// Try to acquire the semaphore for reading.
+ int tryacquire_read (u_short n = 0, int flags = 0) const;
+
+ /// Try to acquire the semaphore for writing.
+ int tryacquire_write (u_short n = 0, int flags = 0) const;
+
+ /// Release the semaphore.
+ int release (u_short n = 0, int flags = 0) const;
+
+ // = Semaphore operation methods.
+ int op (int val, u_short n = 0, int flags = 0) const;
+ int op (sembuf op_vec[], u_short n) const;
+
+ // = Semaphore control methods.
+ int control (int cmd, semun arg, u_short n = 0) const;
+ int control (int cmd, int value = 0, u_short n = 0) const;
+
+ // = Upgrade access control...
+ ACE_USING ACE_SV_Semaphore_Simple::get_id;
+ ACE_USING ACE_SV_Semaphore_Simple::remove;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ static const int BIGCOUNT_;
+ static sembuf op_lock_[2];
+ static sembuf op_endcreate_[2];
+ static sembuf op_open_[1];
+ static sembuf op_close_[3];
+ static sembuf op_unlock_[1];
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Semaphore_Complex.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SV_SEMAPHORE_COMPLEX_H */
diff --git a/ace/IPC/SV_Semaphore_Complex.i b/ace/IPC/SV_Semaphore_Complex.i
new file mode 100644
index 00000000000..82ce23bbbef
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Complex.i
@@ -0,0 +1,83 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SV_Semaphore_Complex.i
+
+#include "ace/Trace.h"
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::acquire (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire");
+ return ACE_SV_Semaphore_Simple::acquire ((u_short) n + 2, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::acquire_read (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_read");
+ return this->acquire (n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::acquire_write (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_write");
+ return this->acquire (n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire");
+ return ACE_SV_Semaphore_Simple::tryacquire ((u_short) n + 2, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire_read (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read");
+ return this->tryacquire (n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::tryacquire_write (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write");
+ return this->tryacquire (n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::release (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::release");
+ return ACE_SV_Semaphore_Simple::release ((u_short) n + 2, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::op (int val, u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
+ return ACE_SV_Semaphore_Simple::op (val, (u_short) n + 2, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::op (sembuf op_vec[], u_short n) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::op");
+ return ACE_SV_Semaphore_Simple::op (op_vec, (u_short) n + 2);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::control (int cmd, semun arg, u_short n) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
+ return ACE_SV_Semaphore_Simple::control (cmd, arg, (u_short) n + 2);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Complex::control (int cmd, int value, u_short n) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Complex::control");
+ return ACE_SV_Semaphore_Simple::control (cmd, value, (u_short) n + 2);
+}
diff --git a/ace/IPC/SV_Semaphore_Simple.cpp b/ace/IPC/SV_Semaphore_Simple.cpp
new file mode 100644
index 00000000000..ebb93233fc1
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Simple.cpp
@@ -0,0 +1,202 @@
+// $Id$
+
+#include "ace/SV_Semaphore_Simple.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Semaphore_Simple.i"
+#endif
+
+ACE_RCSID(ace, SV_Semaphore_Simple, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Simple)
+
+void
+ACE_SV_Semaphore_Simple::dump (void) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::dump");
+}
+
+int
+ACE_SV_Semaphore_Simple::control (int cmd,
+ int value,
+ u_short semnum) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::control");
+ if (this->internal_id_ == -1)
+ return -1;
+ else
+ {
+ semun semctl_arg;
+
+ semctl_arg.val = value;
+ return ACE_OS::semctl (this->internal_id_,
+ semnum,
+ cmd,
+ semctl_arg);
+ }
+}
+
+int
+ACE_SV_Semaphore_Simple::init (key_t k, int i)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::init");
+ this->key_ = k;
+ this->internal_id_ = i;
+ return 0;
+}
+
+// General ACE_SV_Semaphore operation. Increment or decrement by a
+// specific amount (positive or negative; amount can`t be zero).
+
+int
+ACE_SV_Semaphore_Simple::op (int val, u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::op");
+ sembuf op_op;
+
+ op_op.sem_num = n;
+ op_op.sem_flg = flags;
+
+ if (this->internal_id_ == -1)
+ return -1;
+ else if ((op_op.sem_op = val) == 0)
+ return -1;
+ else
+ return ACE_OS::semop (this->internal_id_, &op_op, 1);
+}
+
+// Open or create one or more SV_Semaphores. We return 0 if all is
+// OK, else -1.
+
+int
+ACE_SV_Semaphore_Simple::open (key_t k,
+ int flags,
+ int initial_value,
+ u_short n,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::open");
+ union semun ivalue;
+
+ if (k == IPC_PRIVATE || k == ACE_static_cast (key_t, ACE_INVALID_SEM_KEY))
+ return -1;
+
+ ivalue.val = initial_value;
+ this->key_ = k;
+ this->sem_number_ = n;
+
+ this->internal_id_ = ACE_OS::semget (this->key_, n, perms | flags);
+
+ if (this->internal_id_ == -1)
+ return -1;
+
+ if (ACE_BIT_ENABLED (flags, IPC_CREAT))
+ for (int i = 0; i < n; i++)
+ if (ACE_OS::semctl (this->internal_id_, i, SETVAL, ivalue) == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (key_t k,
+ int flags,
+ int initial_value,
+ u_short n,
+ int perms)
+ : key_ (k)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple");
+ if (this->open (k, flags, initial_value, n, perms) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SV_Semaphore::ACE_SV_Semaphore")));
+}
+
+// Convert name to key. This function is used internally to create keys
+// for the semaphores.
+//
+// The method for generating names is a 32 bit CRC, but still we
+// measured close to collition ratio of nearly 0.1% for
+// ACE::unique_name()-like strings.
+
+key_t
+ACE_SV_Semaphore_Simple::name_2_key (const char *name)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::name_2_key");
+
+ if (name == 0)
+ {
+ errno = EINVAL;
+ return ACE_static_cast (key_t, ACE_INVALID_SEM_KEY);
+ }
+
+ // Basically "hash" the values in the <name>. This won't
+ // necessarily guarantee uniqueness of all keys.
+ // But (IMHO) CRC32 is good enough for most purposes (Carlos)
+ return (key_t) ACE::crc32 (name);
+}
+
+// Open or create a ACE_SV_Semaphore. We return 1 if all is OK, else
+// 0.
+
+int
+ACE_SV_Semaphore_Simple::open (const char *name,
+ int flags,
+ int initial_value,
+ u_short n,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::open");
+
+ key_t key;
+
+ if (name == 0)
+ key = ACE_DEFAULT_SEM_KEY;
+ else
+ key = this->name_2_key (name);
+
+ return this->open (key, flags, initial_value, n, perms);
+}
+
+ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (const char *name,
+ int flags,
+ int initial_value,
+ u_short n,
+ int perms)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple");
+ if (this->open (name,
+ flags,
+ initial_value,
+ n,
+ perms) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple")));
+}
+
+ACE_SV_Semaphore_Simple::~ACE_SV_Semaphore_Simple (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::~ACE_SV_Semaphore_Simple");
+ this->close ();
+}
+
+ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple");
+ this->init ();
+}
+
+// Remove all SV_Semaphores associated with a particular key. This
+// call is intended to be called from a server, for example, when it
+// is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore,
+// regardless of whether other processes may be using it or not. Most
+// other processes should use close() below.
+
+int
+ACE_SV_Semaphore_Simple::remove (void) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::remove");
+ int result = this->control (IPC_RMID);
+ ((ACE_SV_Semaphore_Simple *) this)->init ();
+ return result;
+}
diff --git a/ace/IPC/SV_Semaphore_Simple.h b/ace/IPC/SV_Semaphore_Simple.h
new file mode 100644
index 00000000000..ac6126b2e8c
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Simple.h
@@ -0,0 +1,158 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SV_Semaphore_Simple.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SV_SEMAPHORE_SIMPLE_H
+#define ACE_SV_SEMAPHORE_SIMPLE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SV_Semaphore_Simple
+ *
+ * @brief This is a simple semaphore package that assumes there are
+ * no race conditions for initialization (i.e., the order of
+ * process startup must be well defined).
+ */
+class ACE_Export ACE_SV_Semaphore_Simple
+{
+public:
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_EXCL = IPC_EXCL,
+ ACE_OPEN = 0
+ };
+
+ // = Initialization and termination methods.
+ ACE_SV_Semaphore_Simple (void);
+ ACE_SV_Semaphore_Simple (key_t key,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ ACE_SV_Semaphore_Simple (const char *name,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+ ~ACE_SV_Semaphore_Simple (void);
+
+ int open (const char *name,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Open or create one or more SV_Semaphores. We return 0 if all is
+ /// OK, else -1.
+ int open (key_t key,
+ int flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
+ int initial_value = 1,
+ u_short nsems = 1,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ /// Close a ACE_SV_Semaphore, marking it as invalid for subsequent
+ /// operations...
+ int close (void);
+
+ /**
+ * Remove all SV_Semaphores associated with a particular key. This
+ * call is intended to be called from a server, for example, when it
+ * is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore,
+ * regardless of whether other processes may be using it or not.
+ * Most other processes should use <close> below.
+ */
+ int remove (void) const;
+
+ // = Semaphore acquire and release methods.
+ /**
+ * Wait until a ACE_SV_Semaphore's value is greater than 0, the
+ * decrement it by 1 and return. Dijkstra's P operation, Tannenbaums
+ * DOWN operation.
+ */
+ int acquire (u_short n = 0, int flags = 0) const;
+
+ /// Acquire a semaphore for reading.
+ int acquire_read (u_short n = 0, int flags = 0) const;
+
+ /// Acquire a semaphore for writing
+ int acquire_write (u_short n = 0, int flags = 0) const;
+
+ /// Non-blocking version of <acquire>.
+ int tryacquire (u_short n = 0, int flags = 0) const;
+
+ /// Try to acquire the semaphore for reading.
+ int tryacquire_read (u_short n = 0, int flags = 0) const;
+
+ /// Try to acquire the semaphore for writing.
+ int tryacquire_write (u_short n = 0, int flags = 0) const;
+
+ /// Increment ACE_SV_Semaphore by one. Dijkstra's V operation,
+ /// Tannenbaums UP operation.
+ int release (u_short n = 0, int flags = 0) const;
+
+ // = Semaphore operation methods.
+ /// General ACE_SV_Semaphore operation. Increment or decrement by a
+ /// specific amount (positive or negative; amount can`t be zero).
+ int op (int val, u_short semnum = 0, int flags = SEM_UNDO) const;
+
+ /// General ACE_SV_Semaphore operation on an array of SV_Semaphores.
+ int op (sembuf op_vec[], u_short nsems) const;
+
+ // = Semaphore control methods.
+ int control (int cmd, semun arg, u_short n = 0) const;
+ int control (int cmd, int value = 0, u_short n = 0) const;
+
+ /// Get underlying internal id.
+ int get_id (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Semaphore key.
+ key_t key_;
+
+ /// Internal ID to identify the semaphore group within this process.
+ int internal_id_;
+
+ /// Number of semaphores we're creating.
+ int sem_number_;
+
+ /**
+ * Convert name to key This function is used internally to create
+ * keys for the semaphores. A valid name contains letters and
+ * digits only and MUST start with a letter.
+ *
+ * The method for generating names is not very sophisticated, so
+ * caller should not pass strings which match each other for the first
+ * LUSED characters when he wants to get a different key.
+ */
+ int init (key_t k = ACE_static_cast (key_t, ACE_INVALID_SEM_KEY),
+ int i = -1);
+ key_t name_2_key (const char *name);
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SV_Semaphore_Simple.i"
+#endif
+
+#include "ace/post.h"
+#endif /* _SV_SEMAPHORE_SIMPLE_H */
diff --git a/ace/IPC/SV_Semaphore_Simple.i b/ace/IPC/SV_Semaphore_Simple.i
new file mode 100644
index 00000000000..e18acd95a84
--- /dev/null
+++ b/ace/IPC/SV_Semaphore_Simple.i
@@ -0,0 +1,106 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SV_Semaphore_Simple.i
+
+#include "ace/Trace.h"
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::control (int cmd,
+ semun arg,
+ u_short n) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::control");
+ return this->internal_id_ == -1 ?
+ -1 : ACE_OS::semctl (this->internal_id_, n, cmd, arg);
+}
+
+// Close a ACE_SV_Semaphore, marking it as invalid for subsequent
+// operations...
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::close (void)
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::close");
+ return this->init ();
+}
+
+// General ACE_SV_Semaphore operation on an array of SV_Semaphores.
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::op (sembuf op_vec[], u_short n) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::op");
+ return this->internal_id_ == -1
+ ? -1 : ACE_OS::semop (this->internal_id_, op_vec, n);
+}
+
+// Wait until a ACE_SV_Semaphore's value is greater than 0, the
+// decrement it by 1 and return. Dijkstra's P operation, Tannenbaums
+// DOWN operation.
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::acquire (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire");
+ return this->op (-1, n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::acquire_read (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_read");
+ return this->acquire (n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::acquire_write (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_write");
+ return this->acquire (n, flags);
+}
+
+// Non-blocking version of acquire().
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire");
+ return this->op (-1, n, flags | IPC_NOWAIT);
+}
+
+// Non-blocking version of acquire().
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire_read (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire_read");
+ return this->tryacquire (n, flags);
+}
+
+// Non-blocking version of acquire().
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::tryacquire_write (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire_write");
+ return this->tryacquire (n, flags);
+}
+
+// Increment ACE_SV_Semaphore by one. Dijkstra's V operation,
+// Tannenbaums UP operation.
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::release (u_short n, int flags) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::release");
+ return this->op (1, n, flags);
+}
+
+ASYS_INLINE int
+ACE_SV_Semaphore_Simple::get_id (void) const
+{
+ ACE_TRACE ("ACE_SV_Semaphore_Simple::get_id");
+ return this->internal_id_;
+}
+
diff --git a/ace/IPC/SV_Shared_Memory.cpp b/ace/IPC/SV_Shared_Memory.cpp
new file mode 100644
index 00000000000..dfa73d99c67
--- /dev/null
+++ b/ace/IPC/SV_Shared_Memory.cpp
@@ -0,0 +1,83 @@
+// SV_Shared_Memory.cpp
+// $Id$
+
+#include "ace/SV_Shared_Memory.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/SV_Shared_Memory.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, SV_Shared_Memory, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SV_Shared_Memory)
+
+void
+ACE_SV_Shared_Memory::dump (void) const
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::dump");
+}
+
+// Creates a shared memory segment of SIZE bytes and *does* attach to
+// this segment.
+
+int
+ACE_SV_Shared_Memory::open_and_attach (key_t external_id,
+ size_t sz,
+ int create,
+ int perms,
+ void *virtual_addr,
+ int flags)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::open_and_attach");
+ if (this->open (external_id, sz, create, perms) == -1)
+ return -1;
+ else if (this->attach (virtual_addr, flags) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+// Constructor interface to this->open_and_attach () member function.
+
+ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (key_t external_id,
+ size_t sz,
+ int create,
+ int perms,
+ void *virtual_addr,
+ int flags)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory");
+ if (this->open_and_attach (external_id, sz, create,
+ perms, virtual_addr, flags) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory")));
+}
+
+// The "do nothing" constructor.
+
+ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (void)
+ : internal_id_ (0),
+ size_ (0),
+ segment_ptr_ (0)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory");
+}
+
+// Added this constructor to accept an internal id, the one generated
+// when a server constructs with the key IPC_PRIVATE. The client can
+// be passed ACE_SV_Shared_Memory::internal_id via a socket and call
+// this construtor to attach the existing segment. This prevents
+// having to hard-code a key in advance. Courtesy of Marvin Wolfthal
+// (maw@fsg.com).
+
+ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (ACE_HANDLE int_id,
+ int flags)
+ : internal_id_ (int_id),
+ size_ (0)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory");
+ if (this->attach (0, flags) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory")));
+}
diff --git a/ace/IPC/SV_Shared_Memory.h b/ace/IPC/SV_Shared_Memory.h
new file mode 100644
index 00000000000..977d33f6faa
--- /dev/null
+++ b/ace/IPC/SV_Shared_Memory.h
@@ -0,0 +1,112 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SV_Shared_Memory.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SV_SHARED_MEMORY_H
+#define ACE_SV_SHARED_MEMORY_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SV_Shared_Memory
+ *
+ * @brief This is a wrapper for System V shared memory.
+ */
+class ACE_Export ACE_SV_Shared_Memory
+{
+public:
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_OPEN = 0
+ };
+
+ // = Initialization and termination methods.
+ ACE_SV_Shared_Memory (void);
+ ACE_SV_Shared_Memory (key_t external_id,
+ size_t size,
+ int create,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ void *virtual_addr = 0,
+ int flags = 0);
+
+ ACE_SV_Shared_Memory (ACE_HANDLE internal_id,
+ int flags = 0);
+
+ int open (key_t external_id,
+ size_t size,
+ int create = ACE_SV_Shared_Memory::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS);
+
+ int open_and_attach (key_t external_id,
+ size_t size,
+ int create = ACE_SV_Shared_Memory::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ void *virtual_addr = 0,
+ int flags = 0);
+
+ /// Attach this shared memory segment.
+ int attach (void *virtual_addr = 0,
+ int flags =0);
+
+ /// Detach this shared memory segment.
+ int detach (void);
+
+ /// Remove this shared memory segment.
+ int remove (void);
+
+ /// Forward to underlying System V <shmctl>.
+ int control (int cmd, void *buf);
+
+ // = Segment-related info.
+ void *get_segment_ptr (void) const;
+ int get_segment_size (void) const;
+
+ /// Return the ID of the shared memory segment (i.e., an ACE_HANDLE).
+ ACE_HANDLE get_id (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ enum
+ {
+ /// Most restrictive alignment.
+ ALIGN_WORDB = 8
+ };
+
+ /// Internal identifier.
+ ACE_HANDLE internal_id_;
+
+ /// Size of the mapped segment.
+ int size_;
+
+ /// Pointer to the beginning of the segment.
+ void *segment_ptr_;
+
+ /// Round up to an appropriate page size.
+ int round_up (size_t len);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/SV_Shared_Memory.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SV_SHARED_MEMORY_H */
diff --git a/ace/IPC/SV_Shared_Memory.i b/ace/IPC/SV_Shared_Memory.i
new file mode 100644
index 00000000000..9fd4083ff95
--- /dev/null
+++ b/ace/IPC/SV_Shared_Memory.i
@@ -0,0 +1,114 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SV_Shared_Memory.i
+
+#include "ace/SV_Shared_Memory.h"
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::round_up (size_t len)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::round_up");
+ return (len + ACE_SV_Shared_Memory::ALIGN_WORDB - 1) & ~(ACE_SV_Shared_Memory::ALIGN_WORDB - 1);
+}
+
+// Creates a shared memory segment of SIZE bytes. Does *not* attach
+// this memory segment...
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::open (key_t external_id, size_t sz, int create, int perms)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::open");
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG(perms);
+ ACE_UNUSED_ARG(create);
+ ACE_UNUSED_ARG(sz);
+ ACE_UNUSED_ARG(external_id);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ this->segment_ptr_ = 0;
+ this->size_ = sz;
+
+ this->internal_id_ = ACE_OS::shmget (external_id, sz, create | perms);
+
+ return this->internal_id_ == -1 ? -1 : 0;
+#endif /* ACE_WIN32 */
+}
+
+// Attachs to the shared memory segment.
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::attach (void *virtual_addr, int flags)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::attach");
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG(flags);
+ ACE_UNUSED_ARG(virtual_addr);
+ ACE_NOTSUP_RETURN (-1);
+#else
+ this->segment_ptr_ = ACE_OS::shmat (this->internal_id_, virtual_addr, flags);
+ return this->segment_ptr_ == (void *) -1 ? -1 : 0;
+#endif /* ACE_WIN32 */
+}
+
+// Interface to the underlying shared memory control function.
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::control (int cmd, void *buf)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::control");
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG(cmd);
+ ACE_UNUSED_ARG(buf);
+
+ ACE_NOTSUP_RETURN (-1);
+#else
+ return ACE_OS::shmctl (this->internal_id_, cmd, (struct shmid_ds *) buf);
+#endif /* ACE_WIN32 */
+}
+
+// The overall size of the segment.
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::get_segment_size (void) const
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::get_segment_size");
+ return this->size_;
+}
+
+// Removes the shared memory segment.
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::remove (void)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::remove");
+#if defined (ACE_WIN32)
+ ACE_NOTSUP_RETURN (-1);
+#else
+ return ACE_OS::shmctl (this->internal_id_, IPC_RMID, 0);
+#endif /* ACE_WIN32 */
+}
+
+// Detach the current binding between this->segment_ptr and the shared
+// memory segment.
+
+ACE_INLINE int
+ACE_SV_Shared_Memory::detach (void)
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::detach");
+ return ACE_OS::shmdt (this->segment_ptr_);
+}
+
+ACE_INLINE void *
+ACE_SV_Shared_Memory::get_segment_ptr (void) const
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::get_segment_ptr");
+ return this->segment_ptr_;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_SV_Shared_Memory::get_id (void) const
+{
+ ACE_TRACE ("ACE_SV_Shared_Memory::get_id");
+ return this->internal_id_;
+}
diff --git a/ace/IPC/Signal.cpp b/ace/IPC/Signal.cpp
new file mode 100644
index 00000000000..3bd3d01cedb
--- /dev/null
+++ b/ace/IPC/Signal.cpp
@@ -0,0 +1,861 @@
+// $Id$
+
+#include "ace/Synch_T.h"
+#include "ace/Signal.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+#include "ace/Containers.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Signal.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Signal, "$Id$")
+
+// Static definitions.
+
+#if defined (ACE_HAS_SIG_C_FUNC)
+
+extern "C" void
+ace_sig_handler_dispatch (int signum, siginfo_t *info, ucontext_t *context)
+{
+ ACE_TRACE ("ace_sig_handler_dispatch");
+ ACE_Sig_Handler::dispatch (signum, info, context);
+}
+
+#define ace_signal_handler_dispatcher ACE_SignalHandler(ace_sig_handler_dispatch)
+
+#if !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
+extern "C" void
+ace_sig_handlers_dispatch (int signum, siginfo_t *info, ucontext_t *context)
+{
+ ACE_TRACE ("ace_sig_handlers_dispatch");
+ ACE_Sig_Handlers::dispatch (signum, info, context);
+}
+
+#define ace_signal_handlers_dispatcher ACE_SignalHandler(ace_sig_handlers_dispatch)
+#endif /* ACE_HAS_BROKEN_HPUX_TEMPLATES */
+
+#else
+#define ace_signal_handler_dispatcher ACE_SignalHandler(ACE_Sig_Handler::dispatch)
+
+#if !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
+#define ace_signal_handlers_dispatcher ACE_SignalHandler(ACE_Sig_Handlers::dispatch)
+#endif /* ACE_HAS_BROKEN_HPUX_TEMPLATES */
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+// Array of Event_Handlers that will handle the signals.
+ACE_Event_Handler *ACE_Sig_Handler::signal_handlers_[ACE_NSIG];
+
+// Remembers if a signal has occurred.
+sig_atomic_t ACE_Sig_Handler::sig_pending_ = 0;
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Action)
+
+void
+ACE_Sig_Action::dump (void) const
+{
+ ACE_TRACE ("ACE_Sig_Action::dump");
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Set)
+
+void
+ACE_Sig_Set::dump (void) const
+{
+ ACE_TRACE ("ACE_Sig_Set::dump");
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Guard)
+
+void
+ACE_Sig_Guard::dump (void) const
+{
+ ACE_TRACE ("ACE_Sig_Guard::dump");
+}
+
+ACE_Sig_Action::ACE_Sig_Action (void)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = 0;
+
+ // Since Service_Config::signal_handler_ is static and has an
+ // ACE_Sig_Action instance, Win32 will get errno set unless this is
+ // commented out.
+#if !defined (ACE_WIN32)
+ ACE_OS::sigemptyset (&this->sa_.sa_mask);
+#endif /* ACE_WIN32 */
+ this->sa_.sa_handler = 0;
+}
+
+ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler,
+ sigset_t *sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ if (sig_mask == 0)
+ ACE_OS::sigemptyset (&this->sa_.sa_mask);
+ else
+ this->sa_.sa_mask = *sig_mask; // Structure assignment...
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+}
+
+ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler,
+ const ACE_Sig_Set &sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ // Structure assignment...
+ this->sa_.sa_mask = sig_mask.sigset ();
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+}
+
+ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler,
+ int signum,
+ sigset_t *sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ if (sig_mask == 0)
+ ACE_OS::sigemptyset (&this->sa_.sa_mask);
+ else
+ this->sa_.sa_mask = *sig_mask; // Structure assignment...
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+ ACE_OS::sigaction (signum, &this->sa_, 0);
+}
+
+ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler,
+ int signum,
+ const ACE_Sig_Set &sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ // Structure assignment...
+ this->sa_.sa_mask = sig_mask.sigset ();
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+ ACE_OS::sigaction (signum, &this->sa_, 0);
+}
+
+ACE_Sig_Action::ACE_Sig_Action (const ACE_Sig_Set &signals,
+ ACE_SignalHandler sig_handler,
+ const ACE_Sig_Set &sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ // Structure assignment...
+ this->sa_.sa_mask = sig_mask.sigset ();
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+
+#if (ACE_NSIG > 0) && !defined (CHORUS)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (signals.is_member (s)
+ && ACE_OS::sigaction (s, &this->sa_, 0) == -1)
+ break;
+#else /* ACE_NSIG <= 0 || CHORUS */
+ ACE_UNUSED_ARG (signals);
+#endif /* ACE_NSIG <= 0 || CHORUS */
+}
+
+ACE_Sig_Action::ACE_Sig_Action (const ACE_Sig_Set &signals,
+ ACE_SignalHandler sig_handler,
+ sigset_t *sig_mask,
+ int sig_flags)
+{
+ // ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ this->sa_.sa_flags = sig_flags;
+
+ if (sig_mask == 0)
+ ACE_OS::sigemptyset (&this->sa_.sa_mask);
+ else
+ this->sa_.sa_mask = *sig_mask; // Structure assignment...
+
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (sig_handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+
+#if (ACE_NSIG > 0) && !defined (CHORUS)
+ for (int s = 1; s < ACE_NSIG; s++)
+ if (signals.is_member (s)
+ && ACE_OS::sigaction (s, &this->sa_, 0) == -1)
+ break;
+#else /* ACE_NSIG <= 0 || CHORUS */
+ ACE_UNUSED_ARG (signals);
+#endif /* ACE_NSIG <= 0 || CHORUS */
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handler)
+
+void
+ACE_Sig_Handler::dump (void) const
+{
+ ACE_TRACE ("ACE_Sig_Handler::dump");
+}
+
+int
+ACE_Sig_Handler::sig_pending (void)
+{
+ ACE_TRACE ("ACE_Sig_Handler::sig_pending");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+ return ACE_Sig_Handler::sig_pending_ != 0;
+}
+
+void
+ACE_Sig_Handler::sig_pending (int pending)
+{
+ ACE_TRACE ("ACE_Sig_Handler::sig_pending");
+
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+ ACE_Sig_Handler::sig_pending_ = pending;
+}
+
+ACE_Event_Handler *
+ACE_Sig_Handler::handler (int signum)
+{
+ ACE_TRACE ("ACE_Sig_Handler::handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ if (ACE_Sig_Handler::in_range (signum))
+ return ACE_Sig_Handler::signal_handlers_[signum];
+ else
+ return 0;
+}
+
+ACE_Event_Handler *
+ACE_Sig_Handler::handler_i (int signum,
+ ACE_Event_Handler *new_sh)
+{
+ ACE_TRACE ("ACE_Sig_Handler::handler_i");
+
+ if (ACE_Sig_Handler::in_range (signum))
+ {
+ ACE_Event_Handler *sh = ACE_Sig_Handler::signal_handlers_[signum];
+
+ ACE_Sig_Handler::signal_handlers_[signum] = new_sh;
+ return sh;
+ }
+ else
+ return 0;
+}
+
+ACE_Event_Handler *
+ACE_Sig_Handler::handler (int signum,
+ ACE_Event_Handler *new_sh)
+{
+ ACE_TRACE ("ACE_Sig_Handler::handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ return ACE_Sig_Handler::handler_i (signum, new_sh);
+}
+
+// Register an ACE_Event_Handler along with the corresponding SIGNUM.
+// This method does NOT acquire any locks, so it can be called from a
+// signal handler.
+
+int
+ACE_Sig_Handler::register_handler_i (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **old_sh,
+ ACE_Sig_Action *old_disp)
+{
+ ACE_TRACE ("ACE_Sig_Handler::register_handler_i");
+
+ if (ACE_Sig_Handler::in_range (signum))
+ {
+ ACE_Sig_Action sa; // Define a "null" action.
+ ACE_Event_Handler *sh = ACE_Sig_Handler::handler_i (signum,
+ new_sh);
+
+ // Return a pointer to the old <ACE_Sig_Handler> if the user
+ // asks for this.
+ if (old_sh != 0)
+ *old_sh = sh;
+
+ // Make sure that <new_disp> points to a valid location if the
+ // user doesn't care...
+ if (new_disp == 0)
+ new_disp = &sa;
+
+ new_disp->handler (ace_signal_handler_dispatcher);
+#if !defined (ACE_HAS_LYNXOS_SIGNALS)
+ new_disp->flags (new_disp->flags () | SA_SIGINFO);
+#endif /* ACE_HAS_LYNXOS_SIGNALS */
+ return new_disp->register_action (signum, old_disp);
+ }
+ else
+ return -1;
+}
+
+// Register an ACE_Event_Handler along with the corresponding SIGNUM.
+// This method acquires a lock, so it can't be called from a signal
+// handler, e.g., <dispatch>.
+
+int
+ACE_Sig_Handler::register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **old_sh,
+ ACE_Sig_Action *old_disp)
+{
+ ACE_TRACE ("ACE_Sig_Handler::register_handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ return ACE_Sig_Handler::register_handler_i (signum,
+ new_sh,
+ new_disp,
+ old_sh,
+ old_disp);
+}
+
+// Remove an ACE_Event_Handler.
+
+int
+ACE_Sig_Handler::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int)
+{
+ ACE_TRACE ("ACE_Sig_Handler::remove_handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ if (ACE_Sig_Handler::in_range (signum))
+ {
+ ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0); // Define the default disposition.
+
+ if (new_disp == 0)
+ new_disp = &sa;
+
+ ACE_Sig_Handler::signal_handlers_[signum] = 0;
+
+ // Register either the new disposition or restore the default.
+ return new_disp->register_action (signum, old_disp);
+ }
+ else
+ return -1;
+}
+
+// Master dispatcher function that gets called by a signal handler and
+// dispatches one handler...
+
+void
+ACE_Sig_Handler::dispatch (int signum,
+ siginfo_t *siginfo,
+ ucontext_t *ucontext)
+{
+ ACE_TRACE ("ACE_Sig_Handler::dispatch");
+
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ // We can't use the <sig_pending> call here because that acquires
+ // the lock, which is non-portable...
+ ACE_Sig_Handler::sig_pending_ = 1;
+
+ // Darn well better be in range since the OS dispatched this...
+ ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
+
+ ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
+
+ if (eh != 0)
+ {
+ if (eh->handle_signal (signum, siginfo, ucontext) == -1)
+ {
+ // Define the default disposition.
+ ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0);
+
+ ACE_Sig_Handler::signal_handlers_[signum] = 0;
+
+ // Remove the current disposition by registering the default
+ // disposition.
+ sa.register_action (signum);
+
+ // Allow the event handler to close down if necessary.
+ eh->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::SIGNAL_MASK);
+ }
+#if defined (ACE_WIN32)
+ else
+ // Win32 is weird in the sense that it resets the signal
+ // disposition to SIG_DFL after a signal handler is
+ // dispatched. Therefore, to workaround this "feature" we
+ // must re-register the <ACE_Event_Handler> with <signum>
+ // explicitly.
+ ACE_Sig_Handler::register_handler_i (signum,
+ eh);
+#endif /* ACE_WIN32*/
+ }
+}
+
+ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Sig_Action &sa, int sigkey)
+ : sigkey_ (sigkey),
+ type_ (SIG_ACTION),
+ sa_ (sa)
+{
+ // ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter");
+}
+
+ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Event_Handler *eh,
+ int sigkey)
+ : sigkey_ (sigkey),
+ type_ (ACE_HANDLER),
+ eh_ (eh)
+{
+ // ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter");
+}
+
+ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Sig_Handler_Ex sig_func,
+ int sigkey)
+ : sigkey_ (sigkey),
+ type_ (C_FUNCTION),
+ sig_func_ (sig_func)
+{
+ // ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter");
+}
+
+int
+ACE_Sig_Adapter::sigkey (void)
+{
+ ACE_TRACE ("ACE_Sig_Adapter::sigkey");
+ return this->sigkey_;
+}
+
+int
+ACE_Sig_Adapter::handle_signal (int signum,
+ siginfo_t *siginfo,
+ ucontext_t *ucontext)
+{
+ ACE_TRACE ("ACE_Sig_Adapter::handle_signal");
+
+ switch (this->type_)
+ {
+ case SIG_ACTION:
+ {
+ // We have to dispatch a handler that was registered by a
+ // third-party library.
+
+ ACE_Sig_Action old_disp;
+
+ // Make sure this handler executes in the context it was
+ // expecting...
+ this->sa_.register_action (signum, &old_disp);
+
+ ACE_Sig_Handler_Ex sig_func = ACE_Sig_Handler_Ex (this->sa_.handler ());
+
+ (*sig_func) (signum, siginfo, ucontext);
+ // Restore the original disposition.
+ old_disp.register_action (signum);
+ break;
+ }
+ case ACE_HANDLER:
+ this->eh_->handle_signal (signum, siginfo, ucontext);
+ break;
+ case C_FUNCTION:
+ (*this->sig_func_) (signum, siginfo, ucontext);
+ break;
+ }
+ return 0;
+}
+
+// ----------------------------------------
+// The following classes are local to this file.
+
+// There are bugs with HP/UX's C++ compiler that prevents this stuff
+// from compiling...
+#if !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
+#define ACE_MAX_SIGNAL_HANDLERS ((size_t) 20)
+
+// Keeps track of the id that uniquely identifies each registered
+// signal handler. This id can be used to cancel a timer via the
+// <remove_handler> method.
+int ACE_Sig_Handlers::sigkey_ = 0;
+
+// If this is > 0 then a 3rd party library has registered a
+// handler...
+int ACE_Sig_Handlers::third_party_sig_handler_ = 0;
+
+// Make life easier by defining typedefs...
+typedef ACE_Fixed_Set <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_SET;
+typedef ACE_Fixed_Set_Iterator <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_ITERATOR;
+
+class ACE_Sig_Handlers_Set
+{
+public:
+ static ACE_SIG_HANDLERS_SET *instance (int signum);
+
+private:
+ static ACE_SIG_HANDLERS_SET *sig_handlers_[ACE_NSIG];
+};
+
+/* static */
+ACE_SIG_HANDLERS_SET *ACE_Sig_Handlers_Set::sig_handlers_[ACE_NSIG];
+
+/* static */
+ACE_SIG_HANDLERS_SET *
+ACE_Sig_Handlers_Set::instance (int signum)
+{
+ if (signum <= 0 || signum >= ACE_NSIG)
+ return 0; // This will cause problems...
+ else if (ACE_Sig_Handlers_Set::sig_handlers_[signum] == 0)
+ ACE_NEW_RETURN (ACE_Sig_Handlers_Set::sig_handlers_[signum],
+ ACE_SIG_HANDLERS_SET,
+ 0);
+ return ACE_Sig_Handlers_Set::sig_handlers_[signum];
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handlers)
+
+void
+ACE_Sig_Handlers::dump (void) const
+{
+ ACE_TRACE ("ACE_Sig_Handlers::dump");
+}
+
+// This is the method that does all the dirty work... The basic
+// structure of this method was devised by Detlef Becker.
+
+int
+ACE_Sig_Handlers::register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp,
+ ACE_Event_Handler **,
+ ACE_Sig_Action *old_disp)
+{
+ ACE_TRACE ("ACE_Sig_Handlers::register_handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ if (ACE_Sig_Handler::in_range (signum))
+ {
+ ACE_Sig_Adapter *ace_sig_adapter = 0; // Our signal handler.
+ ACE_Sig_Adapter *extern_sh = 0; // An external signal handler.
+ ACE_Sig_Action sa;
+
+ // Get current signal disposition.
+ sa.retrieve_action (signum);
+
+ // Check whether we are already in control of the signal
+ // handling disposition...
+
+ if (!(sa.handler () == ace_signal_handlers_dispatcher
+ || sa.handler () == ACE_SignalHandler (SIG_IGN)
+ || sa.handler () == ACE_SignalHandler (SIG_DFL)))
+ {
+ // Drat, a 3rd party library has already installed a signal ;-(
+
+ // Upto here we never disabled RESTART_MODE. Thus,
+ // RESTART_MODE can only be changed by 3rd party libraries.
+
+ if (ACE_BIT_DISABLED (sa.flags (), SA_RESTART)
+ && ACE_Sig_Handlers::third_party_sig_handler_)
+ // Toggling is disallowed since we might break 3rd party
+ // code.
+ return -1;
+
+ // Note that we've seen a 3rd party handler...
+ ACE_Sig_Handlers::third_party_sig_handler_ = 1;
+
+ // Create a new 3rd party disposition, remembering its
+ // preferred signal blocking etc...;
+ ACE_NEW_RETURN (extern_sh,
+ ACE_Sig_Adapter (sa,
+ ++ACE_Sig_Handlers::sigkey_),
+ -1);
+ // Add the external signal handler to the set of handlers
+ // for this signal.
+ if (ACE_Sig_Handlers_Set::instance (signum)->insert (extern_sh) == -1)
+ {
+ delete extern_sh;
+ return -1;
+ }
+ }
+ // Add our new handler at this point.
+ ACE_NEW_RETURN (ace_sig_adapter,
+ ACE_Sig_Adapter (new_sh,
+ ++ACE_Sig_Handlers::sigkey_),
+ -1);
+ // Add the ACE signal handler to the set of handlers for this
+ // signal (make sure it goes before the external one if there is
+ // one of these).
+ if (ACE_Sig_Handlers_Set::instance (signum)->insert (ace_sig_adapter) == -1)
+ {
+ // We couldn't reinstall our handler, so let's pretend like
+ // none of this happened...
+ if (extern_sh)
+ {
+ ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
+ delete extern_sh;
+ }
+ delete ace_sig_adapter;
+ return -1;
+ }
+ // If ACE_Sig_Handlers::dispatch() was set we're done.
+ else if (sa.handler () == ace_signal_handlers_dispatcher)
+ return ace_sig_adapter->sigkey ();
+
+ // Otherwise, we need to register our handler function so that
+ // all signals will be dispatched through ACE.
+ else
+ {
+ // Make sure that new_disp points to a valid location if the
+ // user doesn't care...
+ if (new_disp == 0)
+ new_disp = &sa;
+
+ new_disp->handler (ace_signal_handlers_dispatcher);
+
+ // Default is to restart signal handlers.
+ new_disp->flags (new_disp->flags () | SA_RESTART);
+ new_disp->flags (new_disp->flags () | SA_SIGINFO);
+
+ // Finally install (possibly reinstall) the ACE signal
+ // handler disposition with the SA_RESTART mode enabled.
+ if (new_disp->register_action (signum, old_disp) == -1)
+ {
+ // Yikes, lots of roll back at this point...
+ ACE_Sig_Handlers_Set::instance (signum)->remove (ace_sig_adapter);
+ delete ace_sig_adapter;
+
+ if (extern_sh)
+ {
+ ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
+ delete extern_sh;
+ }
+ return -1;
+ }
+ else // Return the signal key so that programs can cancel this
+ // handler if they want!
+ return ace_sig_adapter->sigkey ();
+ }
+ }
+ else
+ return -1;
+}
+
+// Remove the ACE_Event_Handler currently associated with <signum>.
+// Install the new disposition (if given) and return the previous
+// disposition (if desired by the caller). Returns 0 on success and
+// -1 if <signum> is invalid.
+
+int
+ACE_Sig_Handlers::remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp,
+ int sigkey)
+{
+ ACE_TRACE ("ACE_Sig_Handlers::remove_handler");
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+
+ if (ACE_Sig_Handler::in_range (signum))
+ {
+ ACE_SIG_HANDLERS_SET *handler_set =
+ ACE_Sig_Handlers_Set::instance (signum);
+
+ ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
+
+ // Iterate through the set of handlers for this signal.
+
+ for (ACE_Event_Handler **eh;
+ handler_iterator.next (eh) != 0;
+ handler_iterator.advance ())
+ {
+ // Type-safe downcast would be nice here...
+ ACE_Sig_Adapter *sh = (ACE_Sig_Adapter *) *eh;
+
+ // Remove the handler if (1) its key matches the key we've
+ // been told to remove or (2) if we've been told to remove
+ // *all* handlers (i.e., <sigkey> == -1).
+
+ if (sh->sigkey () == sigkey || sigkey == -1)
+ {
+ handler_set->remove (*eh);
+ delete *eh;
+ }
+ }
+
+ if (handler_set->size () == 0)
+ {
+ // If there are no more handlers left for a signal then
+ // register the new disposition or restore the default
+ // disposition.
+
+ ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0);
+
+ if (new_disp == 0)
+ new_disp = &sa;
+
+ return new_disp->register_action (signum, old_disp);
+ }
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Master dispatcher function that gets called by a signal handler and
+// dispatches *all* the handlers...
+
+void
+ACE_Sig_Handlers::dispatch (int signum,
+ siginfo_t *siginfo,
+ ucontext_t *ucontext)
+{
+ ACE_TRACE ("ACE_Sig_Handlers::dispatch");
+ // The following is #ifdef'd out because it's entirely non-portable
+ // to acquire a mutex in a signal handler...
+#if 0
+ ACE_MT (ACE_Recursive_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
+ ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
+#endif /* 0 */
+
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ ACE_Sig_Handler::sig_pending_ = 1;
+
+ // Darn well better be in range since the OS dispatched this...
+ ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
+
+ ACE_SIG_HANDLERS_SET *handler_set =
+ ACE_Sig_Handlers_Set::instance (signum);
+
+ ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
+
+ for (ACE_Event_Handler **eh = 0;
+ handler_iterator.next (eh) != 0;
+ handler_iterator.advance ())
+ {
+ if ((*eh)->handle_signal (signum, siginfo, ucontext) == -1)
+ {
+ handler_set->remove (*eh);
+ delete *eh;
+ }
+ }
+}
+
+// Return the first item in the list of handlers. Note that this will
+// trivially provide the same behavior as the ACE_Sig_Handler
+// version if there is only 1 handler registered!
+
+ACE_Event_Handler *
+ACE_Sig_Handlers::handler (int signum)
+{
+ ACE_TRACE ("ACE_Sig_Handlers::handler");
+ ACE_SIG_HANDLERS_SET *handler_set =
+ ACE_Sig_Handlers_Set::instance (signum);
+ ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
+ ACE_Event_Handler **eh = 0;
+ handler_iterator.next (eh);
+ return *eh;
+}
+
+// The following is a strange bit of logic that tries to give the same
+// semantics as what happens in ACE_Sig_Handler when we replace the
+// current signal handler with a new one. Note that if there is only
+// one signal handler the behavior will be identical. If there is
+// more than one handler then things get weird...
+
+ACE_Event_Handler *
+ACE_Sig_Handlers::handler (int signum, ACE_Event_Handler *new_sh)
+{
+ ACE_TRACE ("ACE_Sig_Handlers::handler");
+ ACE_SIG_HANDLERS_SET *handler_set =
+ ACE_Sig_Handlers_Set::instance (signum);
+ ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
+ ACE_Event_Handler **eh = 0;
+
+ // Find the first handler...
+ handler_iterator.next (eh);
+
+ // ... then remove it from the set ...
+ handler_set->remove (*eh);
+
+ // ... and then insert the new signal handler into the beginning of
+ // the set (note, this is a bit too tied up in the implementation of
+ // ACE_Unbounded_Set...).
+ ACE_Sig_Adapter *temp;
+
+ ACE_NEW_RETURN (temp,
+ ACE_Sig_Adapter (new_sh,
+ ++ACE_Sig_Handlers::sigkey_),
+ 0);
+ handler_set->insert (temp);
+ return *eh;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+ACE_MT (template class ACE_TSS_Guard<ACE_Recursive_Thread_Mutex>);
+ACE_MT (template class ACE_Guard<ACE_Recursive_Thread_Mutex>);
+template class ACE_Fixed_Set<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>;
+template class ACE_Fixed_Set_Iterator<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+#pragma instantiate ACE_TSS_Guard<ACE_Recursive_Thread_Mutex>
+#pragma instantiate ACE_Guard<ACE_Recursive_Thread_Mutex>
+#endif /* ACE_MT_SAFE */
+#pragma instantiate ACE_Fixed_Set<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>
+#pragma instantiate ACE_Fixed_Set_Iterator<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+#endif /* ACE_HAS_BROKEN_HPUX_TEMPLATES */
diff --git a/ace/IPC/Signal.h b/ace/IPC/Signal.h
new file mode 100644
index 00000000000..d51347e7322
--- /dev/null
+++ b/ace/IPC/Signal.h
@@ -0,0 +1,511 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Signal.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SIGNAL_HANDLER_H
+#define ACE_SIGNAL_HANDLER_H
+#include "ace/pre.h"
+
+#if defined (ACE_DONT_INCLUDE_ACE_SIGNAL_H)
+# error ace/Signal.h was #included instead of signal.h by ace/OS.h: fix!!!!
+#endif /* ACE_DONT_INCLUDE_ACE_SIGNAL_H */
+
+#include "ace/Synch.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+
+// This worksaround a horrible bug with HP/UX C++...
+typedef struct sigaction ACE_SIGACTION;
+
+/**
+ * @class ACE_Sig_Set
+ *
+ * @brief Provide a C++ wrapper for the C sigset_t interface.
+ *
+ * Handle signals via a more elegant C++ interface (e.g.,
+ * doesn't require the use of global variables or global
+ * functions in an application).
+ */
+class ACE_Export ACE_Sig_Set
+{
+public:
+ // = Initialization and termination methods.
+ /// Initialize <sigset_> with <sigset>. If <sigset> == 0 then fill
+ /// the set.
+ ACE_Sig_Set (sigset_t *sigset);
+
+ /// Initialize <sigset_> with <sigset>. If <sigset> == 0 then fill
+ /// the set.
+ ACE_Sig_Set (ACE_Sig_Set *sigset);
+
+ /// If <fill> == 0 then initialize the <sigset_> to be empty, else
+ /// full.
+ ACE_Sig_Set (int fill = 0);
+
+ ~ACE_Sig_Set (void);
+
+ /// Create a set that excludes all signals defined by the system.
+ int empty_set (void);
+
+ /// Create a set that includes all signals defined by the system.
+ int fill_set (void);
+
+ /// Adds the individual signal specified by <signo> to the set.
+ int sig_add (int signo);
+
+ /// Deletes the individual signal specified by <signo> from the set.
+ int sig_del (int signo);
+
+ /// Checks whether the signal specified by <signo> is in the set.
+ int is_member (int signo) const;
+
+ /// Returns a pointer to the underlying <sigset_t>.
+ operator sigset_t *();
+
+ /// Returns a copy of the underlying <sigset_t>.
+ sigset_t sigset (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Set of signals.
+ sigset_t sigset_;
+};
+
+/**
+ * @class ACE_Sig_Action
+ *
+ * @brief C++ wrapper facade for the <sigaction> struct.
+ */
+class ACE_Export ACE_Sig_Action
+{
+public:
+ // = Initialization methods.
+ /// Default constructor. Initializes everything to 0.
+ ACE_Sig_Action (void);
+
+ /// Assigns the various fields of a <sigaction> struct but doesn't
+ /// register for signal handling via the <sigaction> function.
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ sigset_t *sigmask = 0,
+ int flags = 0);
+
+ /// Assigns the various fields of a <sigaction> struct but doesn't
+ /// register for signal handling via the <sigaction> function.
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ const ACE_Sig_Set &sigmask,
+ int flags = 0);
+
+ /**
+ * Assigns the various fields of a <sigaction> struct and registers
+ * the <handler> to process signal <signum> via the <sigaction>
+ * function.
+ */
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ int signum,
+ sigset_t *sigmask = 0,
+ int flags = 0);
+
+ /**
+ * Assigns the various fields of a <sigaction> struct and registers
+ * the <handler> to process signal <signum> via the <sigaction>
+ * function.
+ */
+ ACE_Sig_Action (ACE_SignalHandler handler,
+ int signum,
+ const ACE_Sig_Set &sigmask,
+ int flags = 0);
+
+
+ // @@ The next two methods have a parameter as "signalss". Please do
+ // not change the argument name as "signals". This causes the
+ // following problem as reported by
+ // <James.Briggs@dsto.defence.gov.au>.
+
+ // In the file Signal.h two of the functions have and argument name
+ // of signals. signals is a Qt macro (to do with their meta object
+ // stuff.
+ // We could as well have it as "signal", but I am nost sure whether
+ // that would cause a problem with something else - Bala <bala@cs>
+
+ /**
+ * Assigns the various fields of a <sigaction> struct and registers
+ * the <handler> to process all <signals> via the <sigaction>
+ * function.
+ */
+ ACE_Sig_Action (const ACE_Sig_Set &signalss,
+ ACE_SignalHandler handler,
+ const ACE_Sig_Set &sigmask,
+ int flags = 0);
+
+ /**
+ * Assigns the various fields of a <sigaction> struct and registers
+ * the <handler> to process all <signals> via the <sigaction>
+ * function.
+ */
+ ACE_Sig_Action (const ACE_Sig_Set &signalss,
+ ACE_SignalHandler handler,
+ sigset_t *sigmask = 0,
+ int flags = 0);
+
+ /// Copy constructor.
+ ACE_Sig_Action (const ACE_Sig_Action &s);
+
+ /// Default dtor.
+ ~ACE_Sig_Action (void);
+
+ // = Signal action management.
+ /// Register <this> as the current disposition and store old
+ /// disposition into <oaction> if it is non-NULL.
+ int register_action (int signum,
+ ACE_Sig_Action *oaction = 0);
+
+ /// Assign the value of <oaction> to <this> and make it become the
+ /// new signal disposition.
+ int restore_action (int signum,
+ ACE_Sig_Action &oaction);
+
+ /// Retrieve the current disposition into <this>.
+ int retrieve_action (int signum);
+
+ // = Set/get current signal action.
+ void set (struct sigaction *);
+ struct sigaction *get (void);
+ operator ACE_SIGACTION *();
+
+ // = Set/get current signal flags.
+ void flags (int);
+ int flags (void);
+
+ // = Set/get current signal mask.
+ void mask (sigset_t *);
+ void mask (ACE_Sig_Set &);
+ sigset_t *mask (void);
+
+ // = Set/get current signal handler (pointer to function).
+ void handler (ACE_SignalHandler);
+ ACE_SignalHandler handler (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Controls signal behavior.
+ struct sigaction sa_;
+};
+
+/**
+ * @class ACE_Sig_Guard
+ *
+ * @brief Hold signals in MASK for duration of a C++ statement block.
+ * Note that a "0" for mask causes all signals to be held.
+ */
+class ACE_Export ACE_Sig_Guard
+{
+public:
+ // = Initialization and termination methods.
+ /// Block out signals in <mask>. Default is to block all signals!
+ ACE_Sig_Guard (ACE_Sig_Set *mask = 0);
+
+ /// Restore blocked signals.
+ ~ACE_Sig_Guard (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Original signal mask.
+ ACE_Sig_Set omask_;
+};
+
+/**
+ * @class ACE_Sig_Handler
+ *
+ * @brief This is the main dispatcher of signals for ACE. It improves
+ * the existing UNIX signal handling mechanism by allowing C++
+ * objects to handle signals in a way that avoids the use of
+ * global/static variables and functions.
+ *
+ * Using this class a program can register an <ACE_Event_Handler>
+ * with the <ACE_Sig_Handler> in order to handle a designated
+ * <signum>. When a signal occurs that corresponds to this
+ * <signum>, the <handle_signal> method of the registered
+ * <ACE_Event_Handler> is invoked automatically.
+ */
+class ACE_Export ACE_Sig_Handler
+{
+public:
+#if defined (ACE_HAS_WINCE)
+ /// Default ctor/dtor.
+ ACE_Sig_Handler (void);
+ virtual ~ACE_Sig_Handler (void);
+#endif /* ACE_HAS_WINCE */
+
+ // = Registration and removal methods.
+ /**
+ * Add a new <ACE_Event_Handler> and a new sigaction associated with
+ * <signum>. Passes back the existing <ACE_Event_Handler> and its
+ * sigaction if pointers are non-zero. Returns -1 on failure and >=
+ * 0 on success.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /**
+ * Remove the <ACE_Event_Handler> currently associated with
+ * <signum>. <sigkey> is ignored in this implementation since there
+ * is only one instance of a signal handler. Install the new
+ * disposition (if given) and return the previous disposition (if
+ * desired by the caller). Returns 0 on success and -1 if <signum>
+ * is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ // Set/get signal status.
+ /// True if there is a pending signal.
+ static int sig_pending (void);
+
+ /// Reset the value of <sig_pending_> so that no signal is pending.
+ static void sig_pending (int);
+
+ // = Set/get the handler associated with a particular signal.
+
+ /// Return the <ACE_Sig_Handler> associated with <signum>.
+ virtual ACE_Event_Handler *handler (int signum);
+
+ /// Set a new <ACE_Event_Handler> that is associated with <signum>.
+ /// Return the existing handler.
+ virtual ACE_Event_Handler *handler (int signum,
+ ACE_Event_Handler *);
+
+ /**
+ * Callback routine registered with sigaction(2) that dispatches the
+ * <handle_signal> method of the appropriate pre-registered
+ * ACE_Event_Handler.
+ */
+ static void dispatch (int, siginfo_t *,
+ ucontext_t *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = These methods and data members are shared by derived classes.
+
+ /**
+ * Set a new <ACE_Event_Handler> that is associated with <signum>.
+ * Return the existing handler. Does not acquire any locks so that
+ * it can be called from a signal handler, such as <dispatch>.
+ */
+ static ACE_Event_Handler *handler_i (int signum,
+ ACE_Event_Handler *);
+
+ /**
+ * This implementation method is called by <register_handler> and
+ * <dispatch>. It doesn't do any locking so that it can be called
+ * within a signal handler, such as <dispatch>. It adds a new
+ * <ACE_Event_Handler> and a new sigaction associated with <signum>.
+ * Passes back the existing <ACE_Event_Handler> and its sigaction if
+ * pointers are non-zero. Returns -1 on failure and >= 0 on
+ * success.
+ */
+ static int register_handler_i (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /// Check whether the SIGNUM is within the legal range of signals.
+ static int in_range (int signum);
+
+ /// Keeps track of whether a signal is pending.
+ static sig_atomic_t sig_pending_;
+
+private:
+ /// Array used to store one user-defined Event_Handler for every
+ /// signal.
+ static ACE_Event_Handler *signal_handlers_[ACE_NSIG];
+};
+
+/**
+ * @class ACE_Sig_Adapter
+ *
+ * @brief Provide an adapter that transforms various types of signal
+ * handlers into the scheme used by the <ACE_Reactor>.
+ */
+class ACE_Export ACE_Sig_Adapter : public ACE_Event_Handler
+{
+public:
+ ACE_Sig_Adapter (ACE_Sig_Action &, int sigkey);
+ ACE_Sig_Adapter (ACE_Event_Handler *, int sigkey);
+ ACE_Sig_Adapter (ACE_Sig_Handler_Ex, int sigkey = 0);
+ ~ACE_Sig_Adapter (void);
+
+ /// Returns this signal key that's used to remove this from the
+ /// <ACE_Reactor>'s internal table.
+ int sigkey (void);
+
+ /// Called by the <Reactor> to dispatch the signal handler.
+ virtual int handle_signal (int, siginfo_t *, ucontext_t *);
+
+private:
+ /// Key for this signal handler (used to remove it).
+ int sigkey_;
+
+ /// Is this an external handler or an ACE handler?
+ enum
+ {
+ /// We're just wrapping an ACE_Event_Handler.
+ ACE_HANDLER,
+ /// An ACE_Sig_Action.
+ SIG_ACTION,
+ /// A normal C function.
+ C_FUNCTION
+ } type_;
+
+ // = This should be a union, but C++ won't allow that because the
+ // <ACE_Sig_Action> has a constructor.
+ /// This is an external handler (ugh).
+ ACE_Sig_Action sa_;
+
+ /// This is an ACE hander.
+ ACE_Event_Handler *eh_;
+
+ /// This is a normal C function.
+ ACE_Sig_Handler_Ex sig_func_;
+};
+
+#if !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
+/**
+ * @class ACE_Sig_Handlers
+ *
+ * @brief This is an alternative signal handling dispatcher for ACE. It
+ * allows a list of signal handlers to be registered for each
+ * signal. It also makes SA_RESTART the default mode.
+ *
+ * Using this class a program can register one or more
+ * ACE_Event_Handler with the ACE_Sig_Handler in order to
+ * handle a designated <signum>. When a signal occurs that
+ * corresponds to this <signum>, the <handle_signal> methods of
+ * all the registered ACE_Event_Handlers are invoked
+ * automatically.
+ */
+class ACE_Export ACE_Sig_Handlers : public ACE_Sig_Handler
+{
+public:
+ // = Registration and removal methods.
+ /**
+ * Add a new ACE_Event_Handler and a new sigaction associated with
+ * <signum>. Passes back the existing ACE_Event_Handler and its
+ * sigaction if pointers are non-zero. Returns -1 on failure and
+ * a <sigkey> that is >= 0 on success.
+ */
+ virtual int register_handler (int signum,
+ ACE_Event_Handler *new_sh,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Event_Handler **old_sh = 0,
+ ACE_Sig_Action *old_disp = 0);
+
+ /**
+ * Remove an <ACE_Event_Handler> currently associated with <signum>.
+ * We remove the handler if (1) its <sigkey> matches the <sigkey>
+ * passed as a parameter or (2) if we've been told to remove all the
+ * handlers, i.e., <sigkey> == -1. If a new disposition is given it
+ * is installed and the previous disposition is returned (if desired
+ * by the caller). Returns 0 on success and -1 if <signum> is
+ * invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp = 0,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ // = Set/get the handler associated with a particular signal.
+
+ /// Return the head of the list of <ACE_Sig_Handler>s associated with
+ /// SIGNUM.
+ virtual ACE_Event_Handler *handler (int signum);
+
+ /**
+ * Set a new <ACE_Event_Handler> that is associated with SIGNUM at
+ * the head of the list of signals. Return the existing handler
+ * that was at the head.
+ */
+ virtual ACE_Event_Handler *handler (int signum,
+ ACE_Event_Handler *);
+
+ /**
+ * Callback routine registered with sigaction(2) that dispatches the
+ * <handle_signal> method of all the pre-registered
+ * ACE_Event_Handlers for <signum>
+ */
+ static void dispatch (int signum, siginfo_t *, ucontext_t *);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /**
+ * Keeps track of the id that uniquely identifies each registered
+ * signal handler. This id can be used to cancel a timer via the
+ * <remove_handler> method.
+ */
+ static int sigkey_;
+
+ /// If this is > 0 then a 3rd party library has registered a
+ /// handler...
+ static int third_party_sig_handler_;
+};
+#endif /* ACE_HAS_BROKEN_HPUX_TEMPLATES */
+
+#if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" void
+ace_sig_handler_dispatch (int signum, siginfo_t *info, ucontext_t *context);
+
+#if !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
+extern "C" void
+ace_sig_handlers_dispatch (int signum, siginfo_t *info, ucontext_t *context);
+#endif /* ACE_HAS_BROKEN_HPUX_TEMPLATES */
+
+#endif /* ACE_HAS_SIG_C_FUNC */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Signal.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SIGNAL_HANDLER_H */
diff --git a/ace/IPC/Signal.i b/ace/IPC/Signal.i
new file mode 100644
index 00000000000..e2ca95be130
--- /dev/null
+++ b/ace/IPC/Signal.i
@@ -0,0 +1,306 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+ACE_Sig_Set::ACE_Sig_Set (sigset_t *ss)
+ // : sigset_ ()
+{
+ ACE_TRACE ("ACE_Sig_Set::ACE_Sig_Set");
+
+ if (ss == 0)
+ ACE_OS::sigfillset (&this->sigset_);
+ else
+ // Structure assignment.
+ this->sigset_ = *ss;
+}
+
+ACE_INLINE
+ACE_Sig_Set::ACE_Sig_Set (int fill)
+ // : sigset_ ()
+{
+ ACE_TRACE ("ACE_Sig_Set::ACE_Sig_Set");
+
+ if (fill)
+ ACE_OS::sigfillset (&this->sigset_);
+ else
+ ACE_OS::sigemptyset (&this->sigset_);
+}
+
+ACE_INLINE
+ACE_Sig_Set::ACE_Sig_Set (ACE_Sig_Set *ss)
+ // : sigset_ ()
+{
+ ACE_TRACE ("ACE_Sig_Set::ACE_Sig_Set");
+
+ if (ss == 0)
+ ACE_OS::sigfillset (&this->sigset_);
+ else
+ this->sigset_ = ss->sigset_;
+}
+
+ACE_INLINE
+ACE_Sig_Set::~ACE_Sig_Set (void)
+{
+ ACE_TRACE ("ACE_Sig_Set::~ACE_Sig_Set");
+ ACE_OS::sigemptyset (&this->sigset_);
+}
+
+ACE_INLINE int
+ACE_Sig_Set::empty_set (void)
+{
+ ACE_TRACE ("ACE_Sig_Set::empty_set");
+ return ACE_OS::sigemptyset (&this->sigset_);
+}
+
+ACE_INLINE int
+ACE_Sig_Set::fill_set (void)
+{
+ ACE_TRACE ("ACE_Sig_Set::fill_set");
+ return ACE_OS::sigfillset (&this->sigset_);
+}
+
+ACE_INLINE int
+ACE_Sig_Set::sig_add (int signo)
+{
+ ACE_TRACE ("ACE_Sig_Set::sig_add");
+ return ACE_OS::sigaddset (&this->sigset_, signo);
+}
+
+ACE_INLINE int
+ACE_Sig_Set::sig_del (int signo)
+{
+ ACE_TRACE ("ACE_Sig_Set::sig_del");
+ return ACE_OS::sigdelset (&this->sigset_, signo);
+}
+
+ACE_INLINE int
+ACE_Sig_Set::is_member (int signo) const
+{
+ ACE_TRACE ("ACE_Sig_Set::is_member");
+ return ACE_OS::sigismember (ACE_const_cast (sigset_t *, &this->sigset_), signo);
+}
+
+ACE_INLINE
+ACE_Sig_Set::operator sigset_t *(void)
+{
+ ACE_TRACE ("ACE_Sig_Set::operator sigset_t *");
+ return &this->sigset_;
+}
+
+ACE_INLINE sigset_t
+ACE_Sig_Set::sigset (void) const
+{
+ ACE_TRACE ("ACE_Sig_Set::sigset");
+ return this->sigset_;
+}
+
+ACE_INLINE
+ACE_Sig_Action::~ACE_Sig_Action (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::~ACE_Sig_Action");
+}
+
+ACE_INLINE int
+ACE_Sig_Action::flags (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::flags");
+ return this->sa_.sa_flags;
+}
+
+ACE_INLINE void
+ACE_Sig_Action::flags (int flags)
+{
+ ACE_TRACE ("ACE_Sig_Action::flags");
+ this->sa_.sa_flags = flags;
+}
+
+ACE_INLINE sigset_t *
+ACE_Sig_Action::mask (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::mask");
+ return &this->sa_.sa_mask;
+}
+
+ACE_INLINE void
+ACE_Sig_Action::mask (sigset_t *ss)
+{
+ ACE_TRACE ("ACE_Sig_Action::mask");
+ if (ss != 0)
+ this->sa_.sa_mask = *ss; // Structure assignment
+}
+
+ACE_INLINE void
+ACE_Sig_Action::mask (ACE_Sig_Set &ss)
+{
+ ACE_TRACE ("ACE_Sig_Action::mask");
+ this->sa_.sa_mask = ss.sigset (); // Structure assignment
+}
+
+ACE_INLINE ACE_SignalHandler
+ACE_Sig_Action::handler (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::handler");
+ return ACE_SignalHandler (this->sa_.sa_handler);
+}
+
+ACE_INLINE void
+ACE_Sig_Action::handler (ACE_SignalHandler handler)
+{
+ ACE_TRACE ("ACE_Sig_Action::handler");
+#if !defined(ACE_HAS_TANDEM_SIGNALS)
+ this->sa_.sa_handler = ACE_SignalHandlerV (handler);
+#else
+ this->sa_.sa_handler = (void (*)()) ACE_SignalHandlerV (handler);
+#endif /* !ACE_HAS_TANDEM_SIGNALS */
+}
+
+#if 0
+ACE_INLINE ACE_SignalHandler
+ACE_Sig_Action::sigaction (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::sigaction");
+ return ACE_SignalHandler (this->sa_.sa_sigaction);
+}
+
+ACE_INLINE void
+ACE_Sig_Action::sigaction (ACE_SignalHandler handler)
+{
+ ACE_TRACE ("ACE_Sig_Action::sigaction");
+ this->sa_.sa_sigaction = (void (*)()) ACE_SignalHandlerV (handler);
+}
+#endif /* 0 */
+
+ACE_INLINE void
+ACE_Sig_Action::set (struct sigaction *sa)
+{
+ ACE_TRACE ("ACE_Sig_Action::set");
+ this->sa_ = *sa; // Structure assignment.
+}
+
+ACE_INLINE struct sigaction *
+ACE_Sig_Action::get (void)
+{
+ ACE_TRACE ("ACE_Sig_Action::get");
+ return &this->sa_;
+}
+
+ACE_INLINE
+ACE_Sig_Action::operator ACE_SIGACTION * ()
+{
+ ACE_TRACE ("ACE_Sig_Action::operator ACE_SIGACTION *");
+ return &this->sa_;
+}
+
+ACE_INLINE
+ACE_Sig_Action::ACE_Sig_Action (const ACE_Sig_Action &s)
+ // : sa_ ()
+{
+ ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action");
+ *this = s; // structure copy.
+}
+
+ACE_INLINE int
+ACE_Sig_Action::register_action (int signum, ACE_Sig_Action *oaction)
+{
+ ACE_TRACE ("ACE_Sig_Action::register_action");
+ struct sigaction *sa = oaction == 0 ? 0 : oaction->get ();
+
+ return ACE_OS::sigaction (signum, &this->sa_, sa);
+}
+
+ACE_INLINE int
+ACE_Sig_Action::retrieve_action (int signum)
+{
+ ACE_TRACE ("ACE_Sig_Action::retrieve_action");
+ return ACE_OS::sigaction (signum, 0, &this->sa_);
+}
+
+ACE_INLINE int
+ACE_Sig_Action::restore_action (int signum, ACE_Sig_Action &oaction)
+{
+ ACE_TRACE ("ACE_Sig_Action::restore_action");
+ this->sa_ = *oaction.get (); // Structure assignment
+ return ACE_OS::sigaction (signum, &this->sa_, 0);
+}
+
+// Block out the signal MASK until the destructor is called.
+
+ACE_INLINE
+ACE_Sig_Guard::ACE_Sig_Guard (ACE_Sig_Set *mask)
+ : omask_ ()
+{
+ //ACE_TRACE ("ACE_Sig_Guard::ACE_Sig_Guard");
+
+#if defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_UNUSED_ARG (mask);
+#else
+ // If MASK is 0 then block all signals!
+ if (mask == 0)
+ {
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ (sigset_t *) this->omask_);
+# else
+ ACE_OS::thr_sigsetmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ (sigset_t *) this->omask_);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+ }
+ else
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_BLOCK,
+ (sigset_t *) *mask,
+ (sigset_t *)
+ this->omask_);
+# else
+ ACE_OS::thr_sigsetmask (SIG_BLOCK,
+ (sigset_t *) *mask,
+ (sigset_t *)
+ this->omask_);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+}
+
+// Restore the signal mask.
+
+ACE_INLINE
+ACE_Sig_Guard::~ACE_Sig_Guard (void)
+{
+ //ACE_TRACE ("ACE_Sig_Guard::~ACE_Sig_Guard");
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+#if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_SETMASK,
+ (sigset_t *) this->omask_,
+ 0);
+#else
+ ACE_OS::thr_sigsetmask (SIG_SETMASK,
+ (sigset_t *) this->omask_,
+ 0);
+#endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* !ACE_LACKS_UNIX_SIGNALS */
+}
+
+#if defined (ACE_HAS_WINCE)
+ACE_INLINE
+ACE_Sig_Handler::ACE_Sig_Handler (void)
+{
+}
+
+ACE_INLINE
+ACE_Sig_Handler::~ACE_Sig_Handler (void)
+{
+}
+#endif /* ACE_HAS_WINCE */
+
+ACE_INLINE int
+ACE_Sig_Handler::in_range (int signum)
+{
+ ACE_TRACE ("ACE_Sig_Handler::in_range");
+ return signum > 0 && signum < ACE_NSIG;
+}
+
+ACE_INLINE
+ACE_Sig_Adapter::~ACE_Sig_Adapter (void)
+{
+}
diff --git a/ace/IPC/TLI.cpp b/ace/IPC/TLI.cpp
new file mode 100644
index 00000000000..056bc09a0a3
--- /dev/null
+++ b/ace/IPC/TLI.cpp
@@ -0,0 +1,195 @@
+// $Id$
+
+// Defines the member functions for the base class of the ACE_TLI
+// abstraction.
+
+#include "ace/TLI.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, TLI, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI)
+
+void
+ACE_TLI::dump (void) const
+{
+ ACE_TRACE ("ACE_TLI::dump");
+}
+
+ACE_TLI::ACE_TLI (void)
+{
+ ACE_TRACE ("ACE_TLI::ACE_TLI");
+#if defined (ACE_HAS_SVR4_TLI)
+// Solaris 2.4 ACE_TLI option handling is broken. Thus, we must do
+// the memory allocation ourselves... Thanks to John P. Hearn
+// (jph@ccrl.nj.nec.com) for the help.
+
+ this->so_opt_req.opt.maxlen = sizeof (opthdr) + sizeof (long);
+ ACE_NEW (this->so_opt_req.opt.buf,
+ char[this->so_opt_req.opt.maxlen]);
+
+ this->so_opt_ret.opt.maxlen = sizeof (opthdr) + sizeof (long);
+ ACE_NEW (this->so_opt_ret.opt.buf,
+ char[this->so_opt_ret.opt.maxlen]);
+
+ if (this->so_opt_ret.opt.buf == 0)
+ {
+ delete [] this->so_opt_req.opt.buf;
+ this->so_opt_req.opt.buf = 0;
+ return;
+ }
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+ACE_HANDLE
+ACE_TLI::open (const char device[], int oflag, struct t_info *info)
+{
+ ACE_TRACE ("ACE_TLI::open");
+ if (oflag == 0)
+ oflag = O_RDWR;
+ this->set_handle (ACE_OS::t_open ((char *) device, oflag, info));
+
+ return this->get_handle ();
+}
+
+ACE_TLI::~ACE_TLI (void)
+{
+ ACE_TRACE ("ACE_TLI::~ACE_TLI");
+#if defined (ACE_HAS_SVR4_TLI)
+ if (this->so_opt_req.opt.buf)
+ {
+ delete [] this->so_opt_req.opt.buf;
+ delete [] this->so_opt_ret.opt.buf;
+ this->so_opt_req.opt.buf = 0;
+ this->so_opt_ret.opt.buf = 0;
+ }
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+ACE_TLI::ACE_TLI (const char device[], int oflag, struct t_info *info)
+{
+ ACE_TRACE ("ACE_TLI::ACE_TLI");
+ if (this->open (device, oflag, info) == ACE_INVALID_HANDLE)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_TLI::ACE_TLI")));
+}
+
+int
+ACE_TLI::get_local_addr (ACE_Addr &sa) const
+{
+ ACE_TRACE ("ACE_TLI::get_local_addr");
+#if defined (ACE_HAS_SVR4_TLI)
+ struct netbuf name;
+
+ name.maxlen = sa.get_size ();
+ name.buf = (char *) sa.get_addr ();
+
+ if (ACE_OS::ioctl (this->get_handle (), TI_GETMYNAME, &name) == -1)
+/* if (ACE_OS::t_getname (this->get_handle (), &name, LOCALNAME) == -1) */
+ return -1;
+ else
+ return 0;
+#else /* SunOS4 */
+ ACE_UNUSED_ARG (sa);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+int
+ACE_TLI::close (void)
+{
+ ACE_TRACE ("ACE_TLI::close");
+ int result = 0; // Geisler: result must be int
+
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ result = ACE_OS::t_close (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ }
+ return result;
+}
+
+int
+ACE_TLI::set_option (int level, int option, void *optval, int optlen)
+{
+ ACE_TRACE ("ACE_TLI::set_option");
+#if defined (ACE_HAS_SVR4_TLI)
+ /* Set up options for ACE_TLI */
+
+ struct opthdr *opthdr = 0; /* See <sys/socket.h> for details on this format */
+
+ this->so_opt_req.flags = T_NEGOTIATE;
+ this->so_opt_req.opt.len = sizeof *opthdr + OPTLEN (optlen);
+
+ if (this->so_opt_req.opt.len > this->so_opt_req.opt.maxlen)
+ {
+#if !defined (ACE_HAS_SET_T_ERRNO)
+ t_errno = TBUFOVFLW;
+#else
+ set_t_errno (TBUFOVFLW);
+#endif /* ACE_HAS_SET_T_ERRNO */
+ return -1;
+ }
+
+ opthdr = (struct opthdr *) this->so_opt_req.opt.buf;
+ opthdr->level = level;
+ opthdr->name = option;
+ opthdr->len = OPTLEN (optlen);
+ ACE_OS::memcpy (OPTVAL (opthdr), optval, optlen);
+
+ return ACE_OS::t_optmgmt (this->get_handle (), &this->so_opt_req, &this->so_opt_ret);
+#else
+ ACE_UNUSED_ARG (level);
+ ACE_UNUSED_ARG (option);
+ ACE_UNUSED_ARG (optval);
+ ACE_UNUSED_ARG (optlen);
+ return -1;
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+int
+ACE_TLI::get_option (int level, int option, void *optval, int &optlen)
+{
+ ACE_TRACE ("ACE_TLI::get_option");
+#if defined (ACE_HAS_SVR4_TLI)
+ struct opthdr *opthdr = 0; /* See <sys/socket.h> for details on this format */
+
+ this->so_opt_req.flags = T_CHECK;
+ this->so_opt_ret.opt.len = sizeof *opthdr + OPTLEN (optlen);
+
+ if (this->so_opt_ret.opt.len > this->so_opt_ret.opt.maxlen)
+ {
+#if !defined (ACE_HAS_SET_T_ERRNO)
+ t_errno = TBUFOVFLW;
+#else
+ set_t_errno (TBUFOVFLW);
+#endif /* ACE_HAS_SET_T_ERRNO */
+ return -1;
+ }
+
+ opthdr = (struct opthdr *) this->so_opt_req.opt.buf;
+ opthdr->level = level;
+ opthdr->name = option;
+ opthdr->len = OPTLEN (optlen);
+ if (ACE_OS::t_optmgmt (this->get_handle (), &this->so_opt_req, &this->so_opt_ret) == -1)
+ return -1;
+ else
+ {
+ ACE_OS::memcpy (optval, OPTVAL (opthdr), optlen);
+ return 0;
+ }
+#else
+ ACE_UNUSED_ARG (level);
+ ACE_UNUSED_ARG (option);
+ ACE_UNUSED_ARG (optval);
+ ACE_UNUSED_ARG (optlen);
+ return -1;
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+#endif /* ACE_HAS_TLI */
diff --git a/ace/IPC/TLI.h b/ace/IPC/TLI.h
new file mode 100644
index 00000000000..f00e22f48fa
--- /dev/null
+++ b/ace/IPC/TLI.h
@@ -0,0 +1,107 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TLI.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TLI_H
+#define ACE_TLI_H
+#include "ace/pre.h"
+
+#include "ace/IPC_SAP.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+
+#if defined (ACE_HAS_TLI)
+
+// There's not a universal device name for TLI devices. If the platform
+// needs something other than /dev/tcp, it needs to be set up in the config.h
+// file as ACE_TLI_TCP_DEVICE.
+#ifndef ACE_TLI_TCP_DEVICE
+#define ACE_TLI_TCP_DEVICE "/dev/tcp"
+#endif
+
+// There's not a universal device name for XTI/ATM devices. If the platform
+// needs something other than /dev/xtisvc0, it needs to be set up in the
+// config.h file as ACE_XTI_ATM_DEVICE. This may be FORE vendor specific and
+// there may be no good default.
+#ifndef ACE_XTI_ATM_DEVICE
+#define ACE_XTI_ATM_DEVICE "/dev/xtisvc0"
+#endif
+
+/**
+ * @class ACE_TLI
+ *
+ * @brief Defines the member functions for the base class of the
+ * ACE_TLI abstraction.
+ */
+class ACE_Export ACE_TLI : public ACE_IPC_SAP
+{
+public:
+ // = Initialization and termination methods.
+ /// Initialize a TLI endpoint.
+ ACE_HANDLE open (const char device[],
+ int oflag = O_RDWR,
+ struct t_info *info = 0);
+
+ /// Close a TLI endpoint and release resources.
+ int close (void);
+
+ /// Set underlying protocol options.
+ int set_option (int level, int option, void *optval, int optlen);
+
+ /// Get underlying protocol options.
+ int get_option (int level, int option, void *optval, int &optlen);
+
+ // = Calls to underlying TLI operations.
+ int look (void) const;
+ int rcvdis (struct t_discon * = 0) const;
+ int snddis (struct t_call * = 0) const;
+ int sndrel (void) const;
+ int rcvrel (void) const;
+
+ /// Return our local endpoint address.
+ int get_local_addr (ACE_Addr &) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Ensure we are an abstract class.
+ /// Default constructor.
+ /// Destructor.
+ ACE_TLI (void);
+ ~ACE_TLI (void);
+
+ /// Initialize a TLI endpoint.
+ ACE_TLI (const char device[], int oflag = O_RDWR, struct t_info *info = 0);
+
+private:
+#if defined (ACE_HAS_SVR4_TLI)
+ // Insane TLI option management.
+ struct t_optmgmt so_opt_req;
+ struct t_optmgmt so_opt_ret;
+#endif /* ACE_HAS_SVR4_TLI */
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include "ace/post.h"
+#endif /* ACE_TLI_H */
diff --git a/ace/IPC/TLI.i b/ace/IPC/TLI.i
new file mode 100644
index 00000000000..8f32186deaf
--- /dev/null
+++ b/ace/IPC/TLI.i
@@ -0,0 +1,46 @@
+/* -*- C++ -*- */
+// $Id$
+
+// TLI.i
+
+#include "ace/TLI.h"
+
+ACE_INLINE
+int
+ACE_TLI::look (void) const
+{
+ ACE_TRACE ("ACE_TLI::look");
+ return ACE_OS::t_look (this->get_handle ());
+}
+
+ACE_INLINE
+int
+ACE_TLI::rcvdis (struct t_discon *discon) const
+{
+ ACE_TRACE ("ACE_TLI::rcvdis");
+ return ACE_OS::t_rcvdis (this->get_handle (), discon);
+}
+
+ACE_INLINE
+int
+ACE_TLI::snddis (struct t_call *call) const
+{
+ ACE_TRACE ("ACE_TLI::snddis");
+ return ACE_OS::t_snddis (this->get_handle (), call);
+}
+
+ACE_INLINE
+int
+ACE_TLI::rcvrel (void) const
+{
+ ACE_TRACE ("ACE_TLI::rcvrel");
+ return ACE_OS::t_rcvrel (this->get_handle ());
+}
+
+ACE_INLINE
+int
+ACE_TLI::sndrel (void) const
+{
+ ACE_TRACE ("ACE_TLI::sndrel");
+ return ACE_OS::t_sndrel (this->get_handle ());
+}
diff --git a/ace/IPC/TLI_Acceptor.cpp b/ace/IPC/TLI_Acceptor.cpp
new file mode 100644
index 00000000000..29c1717e767
--- /dev/null
+++ b/ace/IPC/TLI_Acceptor.cpp
@@ -0,0 +1,546 @@
+// $Id$
+
+#include "ace/TLI_Acceptor.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, TLI_Acceptor, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+// Put the actual definitions of the ACE_TLI_Request and
+// ACE_TLI_Request_Queue classes here to hide them from clients...
+
+struct ACE_TLI_Request
+{
+ struct t_call *callp_;
+ ACE_HANDLE handle_;
+ ACE_TLI_Request *next_;
+};
+
+class ACE_TLI_Request_Queue
+{
+public:
+ ACE_TLI_Request_Queue (void);
+
+ ACE_HANDLE open (ACE_HANDLE fd, int size);
+ int close (void);
+
+ int enqueue (const char device[], int restart, int rwflag);
+ int dequeue (ACE_TLI_Request *&ptr);
+ int remove (int sequence_number);
+
+ int is_empty (void) const;
+ int is_full (void) const;
+
+ ACE_TLI_Request *alloc (void);
+ void free (ACE_TLI_Request *node);
+
+ void dump (void) const;
+ // Dump the state of an object.
+
+ ACE_ALLOC_HOOK_DECLARE;
+ // Declare the dynamic allocation hooks.
+
+private:
+ ACE_HANDLE handle_;
+ int size_;
+ int current_count_;
+ ACE_TLI_Request *base_;
+ ACE_TLI_Request *tail_;
+ ACE_TLI_Request *free_list_;
+};
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue)
+
+void
+ACE_TLI_Request_Queue::dump (void) const
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::dump");
+}
+
+int
+ACE_TLI_Request_Queue::is_empty (void) const
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
+ return this->current_count_ == 0;
+}
+
+int
+ACE_TLI_Request_Queue::is_full (void) const
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::is_full");
+ return this->current_count_ + 1 == this->size_; // Add 1 for the dummy.
+}
+
+// Add a node to the free list stack.
+
+void
+ACE_TLI_Request_Queue::free (ACE_TLI_Request *node)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::free");
+ node->next_ = this->free_list_;
+ this->free_list_ = node;
+}
+
+// Remove a node from the free list stack.
+
+ACE_TLI_Request *
+ACE_TLI_Request_Queue::alloc (void)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::alloc");
+ ACE_TLI_Request *temp = this->free_list_;
+ this->free_list_ = this->free_list_->next_;
+ return temp;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor)
+
+void
+ACE_TLI_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::dump");
+}
+
+ACE_TLI_Acceptor::ACE_TLI_Acceptor (void)
+ : queue_ (0)
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
+}
+
+int
+ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request *&ptr)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::dequeue");
+ ptr = this->tail_->next_;
+ this->tail_->next_ = ptr->next_;
+ this->current_count_--;
+ return 0;
+}
+
+// This is hideous...
+
+static ACE_HANDLE
+open_new_endpoint (ACE_HANDLE listen_handle,
+ const char dev[],
+ struct t_call *callp,
+ int rwf,
+ ACE_Addr *remote_sap = 0)
+{
+ ACE_TRACE ("open_new_endpoint");
+#if defined (ACE_PSOS)
+ ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
+ S_IRUSR | S_IWUSR,
+ 0);
+#else
+ ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
+ O_RDWR,
+ 0);
+#endif /* ACE_PSOS */
+
+ struct t_bind req, *req_p = 0;
+ if (remote_sap != 0)
+ {
+ req.qlen = 0;
+ req.addr.buf = (char *) remote_sap->get_addr ();
+ req.addr.len = remote_sap->get_size ();
+ req.addr.maxlen = remote_sap->get_size ();
+ req_p = &req;
+ }
+
+ if (fd == ACE_INVALID_HANDLE
+ || ACE_OS::t_bind (fd, req_p, 0) == -1)
+ fd = ACE_INVALID_HANDLE;
+#if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
+ else if (rwf != 0 && ACE_OS::ioctl (fd,
+ I_PUSH,
+ ACE_const_cast (char *, "tirdwr"))
+ == ACE_INVALID_HANDLE)
+ fd = ACE_INVALID_HANDLE;
+#endif /* I_PUSH */
+
+ if (fd == ACE_INVALID_HANDLE)
+ ACE_OS::t_snddis (listen_handle,
+ callp);
+ return fd;
+}
+
+// Close down the acceptor and release resources.
+
+int
+ACE_TLI_Request_Queue::close (void)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::close");
+ int res = 0;
+
+ for (int i = 0; i < this->size_; i++)
+ {
+ ACE_TLI_Request &item = this->base_[i];
+
+ item.handle_ = ACE_INVALID_HANDLE;
+ if (ACE_OS::t_free ((char *) item.callp_,
+ T_CALL) != 0)
+ res = -1;
+ }
+
+ delete [] this->base_;
+ this->base_ = 0;
+ return res;
+}
+
+ACE_HANDLE
+ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::open");
+ this->handle_ = f;
+ this->size_ = sz + 1; // Add one more for the dummy node.
+
+ ACE_NEW_RETURN (this->base_,
+ ACE_TLI_Request[this->size_],
+ ACE_INVALID_HANDLE);
+
+ // Initialize the ACE_Queue and the free list.
+
+ for (int i = 0; i < this->size_; i++)
+ {
+ ACE_TLI_Request *item = &this->base_[i];
+ this->free (item);
+
+ item->handle_ = ACE_INVALID_HANDLE;
+ item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_,
+ T_CALL,
+ T_ALL);
+ if (item->callp_ == 0)
+ return ACE_INVALID_HANDLE;
+ }
+
+ this->tail_ = this->alloc ();
+ this->tail_->next_ = this->tail_;
+ return 0;
+}
+
+ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void)
+ : size_ (0),
+ current_count_ (0),
+ base_ (0),
+ tail_ (0),
+ free_list_ (0)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue");
+}
+
+// Listen for a new connection request and allocate appropriate data
+// structures when one arrives.
+
+int
+ACE_TLI_Request_Queue::enqueue (const char device[],
+ int restart, int rwflag)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::enqueue");
+ ACE_TLI_Request *temp = this->alloc ();
+ ACE_TLI_Request &req = *this->tail_;
+ int res;
+
+ do
+ res = ACE_OS::t_listen (this->handle_, req.callp_);
+ while (res == -1
+ && restart
+ && t_errno == TSYSERR
+ && errno == EINTR);
+
+ if (res != -1)
+ {
+ req.handle_ = open_new_endpoint (this->handle_,
+ device,
+ req.callp_,
+ rwflag);
+ if (req.handle_ != ACE_INVALID_HANDLE)
+ {
+ temp->next_ = this->tail_->next_;
+ this->tail_->next_ = temp;
+ this->tail_ = temp;
+ this->current_count_++;
+ return 0;
+ }
+ }
+
+ // Something must have gone wrong, so free up allocated space.
+ this->free (temp);
+ return -1;
+}
+
+// Locate and remove SEQUENCE_NUMBER from the list of pending
+// connections.
+
+int
+ACE_TLI_Request_Queue::remove (int sequence_number)
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::remove");
+ ACE_TLI_Request *prev = this->tail_;
+
+ // Put the sequence # in the dummy node to simply the search...
+ prev->callp_->sequence = sequence_number;
+
+ ACE_TLI_Request *temp;
+
+ for (temp = this->tail_->next_;
+ temp->callp_->sequence != sequence_number;
+ temp = temp->next_)
+ prev = temp;
+
+ if (temp == this->tail_)
+ // Sequence # was not found, since we're back at the dummy node!
+ return -1;
+ else
+ {
+ prev->next_ = temp->next_;
+ ACE_OS::t_close (temp->handle_);
+ this->current_count_--;
+ this->free (temp);
+ return 0;
+ }
+}
+
+ACE_HANDLE
+ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap,
+ int reuse_addr,
+ int oflag,
+ struct t_info *info,
+ int qlen,
+ const char dev[])
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::open");
+ ACE_HANDLE res = 0;
+ int one = 1;
+
+ this->disp_ = 0;
+
+ ACE_ALLOCATOR_RETURN (this->device_,
+ ACE_OS::strdup (dev),
+ ACE_INVALID_HANDLE);
+ if (this->ACE_TLI::open (dev,
+ oflag,
+ info) == ACE_INVALID_HANDLE)
+ res = ACE_INVALID_HANDLE;
+#if !defined (ACE_HAS_FORE_ATM_XTI)
+ // Reusing the address causes problems with FORE's API. The issue
+ // may be that t_optmgmt isn't fully supported by FORE. t_errno is
+ // TBADOPT after the t_optmgmt call so maybe options are configured
+ // differently for XTI than for TLI (at least for FORE's
+ // implementation - XTI is supposed to be a superset of TLI).
+ else if (reuse_addr
+ && this->set_option (SOL_SOCKET,
+ SO_REUSEADDR,
+ &one,
+ sizeof one) == -1)
+ res = ACE_INVALID_HANDLE;
+#endif /* ACE_HAS_FORE_ATM_XTI */
+ else if ((this->disp_ =
+ (struct t_discon *) ACE_OS::t_alloc (this->get_handle (),
+ T_DIS,
+ T_ALL)) == 0)
+ res = ACE_INVALID_HANDLE;
+ else
+ {
+ struct t_bind req;
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ // Not sure why but FORE's t_bind call won't work if t_bind.qlen
+ // != 1 Adjust the backlog accordingly.
+ this->backlog_ = 1;
+ req.qlen = 1;
+#else
+ this->backlog_ = qlen;
+ req.qlen = qlen;
+#endif /* ACE_HAS_FORE_ATM_XTI */
+ req.addr.maxlen = remote_sap.get_size ();
+
+ if (remote_sap == ACE_Addr::sap_any)
+ // Note that if addr.len == 0 then ACE_TLI selects the port
+ // number.
+ req.addr.len = 0;
+ else
+ {
+ req.addr.buf = (char *) remote_sap.get_addr ();
+ req.addr.len = remote_sap.get_size ();
+ }
+
+ res = (ACE_HANDLE) ACE_OS::t_bind (this->get_handle (),
+ &req,
+ 0);
+ if (res != ACE_INVALID_HANDLE)
+ {
+ ACE_NEW_RETURN (this->queue_,
+ ACE_TLI_Request_Queue,
+ ACE_INVALID_HANDLE);
+ res = this->queue_->open (this->get_handle (),
+ this->backlog_);
+ }
+ }
+ if (res == ACE_INVALID_HANDLE)
+ this->close ();
+ return this->get_handle ();
+}
+
+ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
+ int reuse_addr,
+ int oflag,
+ struct t_info *info,
+ int back,
+ const char dev[])
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
+ if (this->open (remote_sap,
+ reuse_addr,
+ oflag,
+ info,
+ back,
+ dev) == ACE_INVALID_HANDLE)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor")));
+}
+
+int
+ACE_TLI_Acceptor::close (void)
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::close");
+ if (this->device_ != 0)
+ {
+ if (this->queue_ != 0)
+ {
+ this->queue_->close ();
+ delete this->queue_;
+ }
+
+ ACE_OS::t_free ((char *) this->disp_, T_DIS);
+ ACE_OS::free (ACE_MALLOC_T (this->device_));
+ this->disp_ = 0;
+ this->device_ = 0;
+ return this->ACE_TLI::close ();
+ }
+ return 0;
+}
+
+// Perform the logic required to handle the arrival of asynchronous
+// events while we are trying to accept a new connection request.
+
+int
+ACE_TLI_Acceptor::handle_async_event (int restart, int rwf)
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event");
+ int event = this->look ();
+
+ switch (event)
+ {
+ case T_DISCONNECT:
+ this->rcvdis (this->disp_);
+ this->queue_->remove (this->disp_->sequence);
+ break;
+ case T_LISTEN:
+ this->queue_->enqueue (this->device_,
+ restart,
+ rwf);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int
+ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle,
+ int rwf,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::accept");
+ ACE_UNUSED_ARG (reset_new_handle);
+
+ ACE_TLI_Request *req = 0;
+ int res = 0;
+ if (timeout != 0
+ && ACE::handle_timed_accept (this->get_handle (),
+ timeout,
+ restart) == -1)
+ return -1;
+ else if (this->queue_->is_empty ())
+ {
+ req = this->queue_->alloc ();
+
+ do
+ res = ACE_OS::t_listen (this->get_handle (),
+ req->callp_);
+ while (res == -1
+ && restart
+ && errno == EINTR);
+
+ if (res != -1)
+ {
+ req->handle_ = open_new_endpoint (this->get_handle (),
+ this->device_,
+ req->callp_,
+ rwf
+#if defined (ACE_WIN32)
+ , remote_addr
+#endif /* ACE_WIN32 */
+ );
+ if (req->handle_ == ACE_INVALID_HANDLE)
+ res = -1;
+ else
+ res = 0;
+ }
+ }
+ else
+ res = this->queue_->dequeue (req);
+
+ if (udata != 0)
+ ACE_OS::memcpy ((void *) &req->callp_->udata,
+ (void *) udata,
+ sizeof *udata);
+ if (opt != 0)
+ ACE_OS::memcpy ((void *) &req->callp_->opt,
+ (void *) opt,
+ sizeof *opt);
+
+ while (res != -1)
+ {
+ res = ACE_OS::t_accept (this->get_handle (),
+ req->handle_,
+ req->callp_);
+ if (res != -1)
+ break; // Got one!
+ else if (t_errno == TLOOK)
+ res = this->handle_async_event (restart, rwf);
+ else if (restart && t_errno == TSYSERR && errno == EINTR)
+ res = 0;
+ }
+
+ if (res == -1)
+ {
+ if (errno != EWOULDBLOCK)
+ {
+ new_tli_sap.set_handle (ACE_INVALID_HANDLE);
+ if (req->handle_ != ACE_INVALID_HANDLE)
+ ACE_OS::t_close (req->handle_);
+ }
+ }
+ else
+ {
+ new_tli_sap.set_handle (req->handle_);
+
+ if (remote_addr != 0)
+ remote_addr->set_addr ((void *) req->callp_->addr.buf,
+ req->callp_->addr.len);
+ }
+
+ req->handle_ = ACE_INVALID_HANDLE;
+ this->queue_->free (req);
+ new_tli_sap.set_rwflag (rwf);
+ return new_tli_sap.get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+#endif /* ACE_HAS_TLI */
diff --git a/ace/IPC/TLI_Acceptor.h b/ace/IPC/TLI_Acceptor.h
new file mode 100644
index 00000000000..2112bf4535c
--- /dev/null
+++ b/ace/IPC/TLI_Acceptor.h
@@ -0,0 +1,118 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TLI_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TLI_ACCEPTOR_H
+#define ACE_TLI_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/TLI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+#include "ace/TLI_Stream.h"
+
+#if defined (ACE_HAS_TLI)
+
+// Forward reference...
+class ACE_TLI_Request_Queue;
+
+/**
+ * @class ACE_TLI_Acceptor
+ *
+ * @brief Defines the member functions for ACE_TLI_Acceptor abstraction.
+ *
+ * This class implements the algorithm described in Steve Rago's
+ * book on System V UNIX network programming. It basically
+ * makes TLI look like the C++ SOCK_SAP socket wrappers with
+ * respect to establishing passive-mode listener endpoints.
+ */
+class ACE_Export ACE_TLI_Acceptor : public ACE_TLI
+{
+public:
+ friend class ACE_Request_Queue;
+
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_TLI_Acceptor (void);
+
+ /// Initiate a passive mode socket.
+ ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
+ int reuse_addr = 0,
+ int oflag = O_RDWR,
+ struct t_info *info = 0,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ const char device[] = ACE_TLI_TCP_DEVICE);
+
+ /// Initiate a passive mode socket.
+ ACE_HANDLE open (const ACE_Addr &remote_sap,
+ int reuse_addr = 0,
+ int oflag = O_RDWR,
+ struct t_info *info = 0,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ const char device[] = ACE_TLI_TCP_DEVICE);
+
+ /// Close down the acceptor and release resources.
+ int close (void);
+
+ // = Passive connection acceptance method.
+
+ /**
+ * Accept a new data transfer connection. A <timeout> of 0 means
+ * block forever, a <timeout> of {0, 0} means poll. <restart> == 1
+ * means "restart if interrupted."
+ */
+ int accept (ACE_TLI_Stream &new_tli_sap,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0,
+ int rwflag = 1,
+ netbuf *udata = 0,
+ netbuf *opt = 0);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+ typedef ACE_TLI_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Network "device" we are using.
+ const char *device_;
+
+ /// Number of connections to queue.
+ int backlog_;
+
+ /// Are we using "tirdwr" mod?
+ int rwflag_;
+
+ /// Handle TLI accept insanity...
+ int handle_async_event (int restart, int rwflag);
+
+ /// Used for queueing up pending requests.
+ ACE_TLI_Request_Queue *queue_;
+
+ /// Used for handling disconnects
+ struct t_discon *disp_;
+};
+
+#endif /* ACE_HAS_TLI */
+#include "ace/post.h"
+#endif /* ACE_TLI_ACCEPTOR_H */
diff --git a/ace/IPC/TLI_Connector.cpp b/ace/IPC/TLI_Connector.cpp
new file mode 100644
index 00000000000..cca3ff1d265
--- /dev/null
+++ b/ace/IPC/TLI_Connector.cpp
@@ -0,0 +1,247 @@
+// TLI_Connector.cpp
+// $Id$
+
+#include "ace/Handle_Set.h"
+#include "ace/TLI_Connector.h"
+
+ACE_RCSID(ace, TLI_Connector, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI_Connector.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector)
+
+void
+ACE_TLI_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_TLI_Connector::dump");
+}
+
+ACE_TLI_Connector::ACE_TLI_Connector (void)
+{
+ ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
+}
+
+// Connect the <new_stream> to the <remote_sap>, waiting up to
+// <timeout> amount of time if necessary. It's amazing how
+// complicated this is to do in TLI...
+
+int
+ACE_TLI_Connector::connect (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int /* perms */,
+ const char device[],
+ struct t_info *info,
+ int rwf,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_TLI_Connector::connect");
+ int result = 0;
+
+ // Only open a new endpoint if we don't already have a valid handle.
+
+ if (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && new_stream.open (device, flags, info) == ACE_INVALID_HANDLE)
+ return -1;
+
+ if (local_sap != ACE_Addr::sap_any)
+ {
+ // Bind the local endpoint to a specific addr.
+
+ struct t_bind *localaddr;
+
+ localaddr = (struct t_bind *)
+ ACE_OS::t_alloc (new_stream.get_handle (), T_BIND, T_ADDR);
+
+ if (localaddr == 0)
+ result = -1;
+ else
+ {
+ int one = 1;
+#if !defined (ACE_HAS_FORE_ATM_XTI)
+ // Reusing the address causes problems with FORE's API. The
+ // issue may be that t_optmgmt isn't fully supported by
+ // FORE. t_errno is TBADOPT after the t_optmgmt call so
+ // maybe options are configured differently for XTI than for
+ // TLI (at least for FORE's implementation - XTI is supposed
+ // to be a superset of TLI).
+ if (reuse_addr
+ && new_stream.set_option (SOL_SOCKET,
+ SO_REUSEADDR,
+ &one,
+ sizeof one) == -1)
+ result = -1;
+ else
+#endif /* ACE_HAS_FORE_ATM_XTI */
+ {
+ void *addr_buf = local_sap.get_addr ();
+ localaddr->addr.len = local_sap.get_size ();
+ ACE_OS::memcpy(localaddr->addr.buf,
+ addr_buf,
+ localaddr->addr.len);
+
+ if (ACE_OS::t_bind (new_stream.get_handle (),
+ localaddr,
+ localaddr) == -1)
+ result = -1;
+
+ ACE_OS::t_free ((char *) localaddr,
+ T_BIND);
+ }
+ }
+
+ if (result == -1)
+ {
+ new_stream.close ();
+ return -1;
+ }
+ }
+ // Let TLI select the local endpoint addr.
+ else if (ACE_OS::t_bind (new_stream.get_handle (), 0, 0) == -1)
+ return -1;
+
+ struct t_call *callptr = 0;
+
+ callptr = (struct t_call *)
+ ACE_OS::t_alloc (new_stream.get_handle (), T_CALL, T_ADDR);
+
+ if (callptr == 0)
+ {
+ new_stream.close ();
+ return -1;
+ }
+
+ void *addr_buf = remote_sap.get_addr ();
+ callptr->addr.len = remote_sap.get_size ();
+ ACE_OS::memcpy (callptr->addr.buf,
+ addr_buf,
+ callptr->addr.len);
+ //callptr->addr.buf = (char *) remote_sap.get_addr ();
+
+ if (udata != 0)
+ ACE_OS::memcpy ((void *) &callptr->udata, (void *) udata, sizeof *udata);
+ if (opt != 0)
+ ACE_OS::memcpy ((void *) &callptr->opt, (void *) opt, sizeof *opt);
+
+ // Connect to remote endpoint.
+#if defined (ACE_HAS_FORE_ATM_XTI)
+ // FORE's XTI/ATM driver has problems with ioctl/fcntl calls so (at least
+ // for now) always have blocking calls.
+ timeout = 0;
+#endif /* ACE_HAS_FORE_ATM_XTI */
+
+ if (timeout != 0) // Enable non-blocking, if required.
+ {
+ if (new_stream.enable (ACE_NONBLOCK) == -1)
+ result = -1;
+
+ // Do a non-blocking connect.
+ if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
+ {
+ result = -1;
+
+ // Check to see if we simply haven't connected yet on a
+ // non-blocking handle or whether there's really an error.
+ if (t_errno == TNODATA)
+ {
+ if (timeout->sec () == 0 && timeout->usec () == 0)
+ errno = EWOULDBLOCK;
+ else
+ result = this->complete (new_stream, 0, timeout);
+ }
+ else if (t_errno == TLOOK && new_stream.look () == T_DISCONNECT)
+ new_stream.rcvdis ();
+ }
+ }
+ // Do a blocking connect to the server.
+ else if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
+ result = -1;
+
+ if (result != -1)
+ {
+ new_stream.set_rwflag (rwf);
+#if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
+ if (new_stream.get_rwflag ())
+ result = ACE_OS::ioctl (new_stream.get_handle (),
+ I_PUSH,
+ ACE_const_cast (char *, "tirdwr"));
+#endif /* I_PUSH */
+ }
+ else if (!(errno == EWOULDBLOCK || errno == ETIME))
+ {
+ // If things have gone wrong, close down and return an error.
+ new_stream.close ();
+ new_stream.set_handle (ACE_INVALID_HANDLE);
+ }
+
+ if (ACE_OS::t_free ((char *) callptr, T_CALL) == -1)
+ return -1;
+ return result;
+}
+
+// Try to complete a non-blocking connection.
+
+int
+ACE_TLI_Connector::complete (ACE_TLI_Stream &new_stream,
+ ACE_Addr *remote_sap,
+ ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_TLI_Connector::complete");
+#if defined (ACE_WIN32)
+ if (WaitForSingleObject (new_stream.get_handle(), tv->msec()) == WAIT_OBJECT_0)
+ {
+ if (ACE_OS::t_look (new_stream.get_handle()) == T_CONNECT)
+ return t_rcvconnect (new_stream.get_handle(), 0);
+ else
+ return -1;
+ }
+ else
+ return -1;
+#else
+ ACE_HANDLE h = ACE::handle_timed_complete (new_stream.get_handle (),
+ tv,
+ 1);
+ if (h == ACE_INVALID_HANDLE)
+ {
+ new_stream.close ();
+ return -1;
+ }
+ else // We've successfully connected!
+ {
+ if (remote_sap != 0)
+ {
+#if defined (ACE_HAS_SVR4_TLI)
+ struct netbuf name;
+
+ name.maxlen = remote_sap->get_size ();
+ name.buf = (char *) remote_sap->get_addr ();
+
+ if (ACE_OS::ioctl (new_stream.get_handle (),
+ TI_GETPEERNAME,
+ &name) == -1)
+#else /* SunOS4 */
+ if (0)
+#endif /* ACE_HAS_SVR4_TLI */
+ {
+ new_stream.close ();
+ return -1;
+ }
+ }
+
+ // Start out with non-blocking disabled on the <new_stream>.
+ new_stream.disable (ACE_NONBLOCK);
+
+ return 0;
+ }
+#endif /* ACE_WIN32 */
+}
+
+#endif /* ACE_HAS_TLI */
diff --git a/ace/IPC/TLI_Connector.h b/ace/IPC/TLI_Connector.h
new file mode 100644
index 00000000000..785f109712a
--- /dev/null
+++ b/ace/IPC/TLI_Connector.h
@@ -0,0 +1,126 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TLI_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TLI_CONNECTOR_H
+#define ACE_TLI_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/TLI_Stream.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_TLI)
+
+/**
+ * @class ACE_TLI_Connector
+ *
+ * @brief Defines an active connection factory for the ACE_TLI C++
+ * wrappers.
+ */
+class ACE_Export ACE_TLI_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_TLI_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ ACE_TLI_Connector (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0,
+ const char device[] = ACE_TLI_TCP_DEVICE,
+ struct t_info *info = 0,
+ int rw_flag = 1,
+ struct netbuf *udata = 0,
+ struct netbuf *opt = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0,
+ const char device[] = ACE_TLI_TCP_DEVICE,
+ struct t_info *info = 0,
+ int rw_flag = 1,
+ struct netbuf *udata = 0,
+ struct netbuf *opt = 0);
+
+ /**
+ * Try to complete a non-blocking connection.
+ * If connection completion is successful then <new_stream> contains
+ * the connected ACE_SOCK_Stream. If <remote_sap> is non-NULL then it
+ * will contain the address of the connected peer.
+ */
+ int complete (ACE_TLI_Stream &new_stream,
+ ACE_Addr *remote_sap,
+ ACE_Time_Value *tv);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+ typedef ACE_TLI_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI_Connector.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include "ace/post.h"
+#endif /* ACE_TLI_CONNECTOR_H */
diff --git a/ace/IPC/TLI_Connector.i b/ace/IPC/TLI_Connector.i
new file mode 100644
index 00000000000..e40a1c2637c
--- /dev/null
+++ b/ace/IPC/TLI_Connector.i
@@ -0,0 +1,47 @@
+/* -*- C++ -*- */
+// $Id$
+
+// TLI_Connector.i
+
+ACE_INLINE
+ACE_TLI_Connector::ACE_TLI_Connector (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ const char device[],
+ struct t_info *info,
+ int rwf,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
+ if (this->connect (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ device,
+ info,
+ rwf,
+ udata,
+ opt) == -1
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_TLI_Stream::ACE_TLI_Stream")));
+}
+
+ACE_INLINE
+int
+ACE_TLI_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_UNUSED_ARG (handle);
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
+
diff --git a/ace/IPC/TLI_Stream.cpp b/ace/IPC/TLI_Stream.cpp
new file mode 100644
index 00000000000..a5533d40492
--- /dev/null
+++ b/ace/IPC/TLI_Stream.cpp
@@ -0,0 +1,110 @@
+// $Id$
+
+/* Defines the member functions for the base class of the ACE_TLI_Stream
+ abstraction. */
+
+#include "ace/TLI_Stream.h"
+
+ACE_RCSID(ace, TLI_Stream, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TLI_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Stream)
+
+void
+ACE_TLI_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::dump");
+}
+
+ACE_TLI_Stream::ACE_TLI_Stream (void)
+ : rwflag_ (0)
+{
+ ACE_TRACE ("ACE_TLI_Stream::ACE_TLI_Stream");
+}
+
+int
+ACE_TLI_Stream::get_remote_addr (ACE_Addr &sa) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::get_remote_addr");
+
+#if defined (ACE_HAS_SVR4_TLI)
+ struct netbuf name;
+ name.maxlen = sa.get_size ();
+ name.buf = (char *) sa.get_addr ();
+
+ // if (ACE_OS::t_getname (this->get_handle (), &name, REMOTENAME) == -1)
+ if (ACE_OS::ioctl (this->get_handle (),
+ TI_GETPEERNAME,
+ &name) == -1)
+ return -1;
+ else
+ return 0;
+#else /* SunOS4 */
+ ACE_UNUSED_ARG (sa);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_SVR4_TLI */
+}
+
+// Send a release and then await the release from the other side.
+
+int
+ACE_TLI_Stream::active_close (void)
+{
+ ACE_TRACE ("ACE_TLI_Stream::active_close");
+ char buf;
+
+ if (this->sndrel () == -1)
+ return -1;
+ else if (this->recv (&buf, sizeof buf) == -1)
+ {
+ if (t_errno == TLOOK && this->look () == T_ORDREL)
+ {
+ if (this->rcvrel () == -1)
+ return -1;
+ }
+ else
+ return -1;
+ }
+
+ return this->close ();
+}
+
+// Acknowledge the release from the other side and then send the
+// release to the other side.
+
+int
+ACE_TLI_Stream::passive_close (void)
+{
+ ACE_TRACE ("ACE_TLI_Stream::passive_close");
+
+ if (this->rcvrel () == -1)
+ return -1;
+ else if (this->sndrel () == -1)
+ return -1;
+
+ return this->close ();
+}
+
+int
+ACE_TLI_Stream::close (void)
+{
+ ACE_TRACE ("ACE_TLI_Stream::close");
+
+ ACE_HANDLE fd = this->get_handle ();
+
+ this->set_handle (ACE_INVALID_HANDLE);
+
+#if !defined (ACE_WIN32)
+ if (this->rwflag_)
+ return ACE_OS::close (fd);
+ else
+#endif /* ACE_WIN32 */
+ return ACE_OS::t_close (fd);
+}
+
+#endif /* ACE_HAS_TLI */
diff --git a/ace/IPC/TLI_Stream.h b/ace/IPC/TLI_Stream.h
new file mode 100644
index 00000000000..ba5c08299e4
--- /dev/null
+++ b/ace/IPC/TLI_Stream.h
@@ -0,0 +1,129 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TLI_Stream.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_TLI_STREAM_H
+#define ACE_TLI_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/TLI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+
+#if defined (ACE_HAS_TLI)
+
+/**
+ * @class ACE_TLI_Stream
+ *
+ * @brief Defines the member functions for ACE_TLI_Stream abstraction.
+ */
+class ACE_Export ACE_TLI_Stream : public ACE_TLI
+{
+public:
+ friend class ACE_TLI_Acceptor;
+ friend class ACE_TLI_Connector;
+
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_TLI_Stream (void);
+
+ // = TLI-specific shutdown operations.
+ /// Close down and release resources.
+ int close (void);
+
+ /// Send a release and then await the release from the other side.
+ int active_close (void);
+
+ /// Acknowledge the release from the other side and then send the
+ /// release to the other side.
+ int passive_close (void);
+
+ /// Return address of remotely connected peer.
+ int get_remote_addr (ACE_Addr &) const;
+
+ // = timod bindings
+ /// Send an n byte buffer to the connected socket (uses t_snd(3)).
+ /// Recv an n byte buffer from the connected socket (uses t_rcv(3)).
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+ ssize_t recv (void *buf,
+ size_t n,
+ int *flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send exactly n bytes to the connected socket (uses t_snd(3)).
+ /// Recv exactly n bytes from the connected socket (uses t_rcv(3)).
+ ssize_t send_n (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+ ssize_t recv_n (void *buf,
+ size_t n,
+ int *flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ // = tirdwr bindings
+ /// Send an n byte buffer to the connected socket (uses write(2)).
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an n byte buffer from the connected socket (uses read(2)).
+ ssize_t recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send n bytes, keep trying until n are sent (uses write(2)).
+ ssize_t send_n (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Recv n bytes, keep trying until n are received (uses read (2)).
+ ssize_t recv_n (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Indicates whether the tirdwr module should be pushed
+ int rwflag_;
+
+ // = Get/set rwflag
+ int get_rwflag (void);
+ void set_rwflag (int);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/TLI_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_TLI */
+#include "ace/post.h"
+#endif /* ACE_TLI_STREAM_H */
diff --git a/ace/IPC/TLI_Stream.i b/ace/IPC/TLI_Stream.i
new file mode 100644
index 00000000000..8452138cea1
--- /dev/null
+++ b/ace/IPC/TLI_Stream.i
@@ -0,0 +1,149 @@
+/* -*- C++ -*- */
+// $Id$
+
+// TLI_Stream.i
+
+#include "ace/TLI_Stream.h"
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::send");
+ return ACE::send (this->get_handle (),
+ buf,
+ n,
+ timeout);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::send");
+ return ACE::t_snd (this->get_handle (),
+ buf,
+ n,
+ flags,
+ timeout);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::recv");
+ return ACE::recv (this->get_handle (),
+ buf,
+ n,
+ timeout);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::recv (void *buf,
+ size_t n,
+ int *flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::recv");
+ int f = 0;
+
+ if (flags == 0)
+ flags = &f;
+
+ return ACE::t_rcv (this->get_handle (),
+ buf,
+ n,
+ flags,
+ timeout);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::send_n (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::send_n (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::send_n");
+
+ return ACE::t_snd_n (this->get_handle (),
+ buf,
+ n,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::recv_n (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE
+ssize_t
+ACE_TLI_Stream::recv_n (void *buf,
+ size_t n,
+ int *flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_TLI_Stream::recv_n");
+
+ return ACE::t_rcv_n (this->get_handle (),
+ buf,
+ n,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ACE_INLINE
+void
+ACE_TLI_Stream::set_rwflag (int value)
+{
+ ACE_TRACE ("ACE_TLI_Stream::set_rwflag");
+ this->rwflag_ = value;
+}
+
+ACE_INLINE
+int
+ACE_TLI_Stream::get_rwflag (void)
+{
+ ACE_TRACE ("ACE_TLI_Stream::get_rwflag");
+ return this->rwflag_;
+}
diff --git a/ace/IPC/TTY_IO.cpp b/ace/IPC/TTY_IO.cpp
new file mode 100644
index 00000000000..8e0e17bb3c1
--- /dev/null
+++ b/ace/IPC/TTY_IO.cpp
@@ -0,0 +1,436 @@
+// $Id$
+
+#include "ace/TTY_IO.h"
+
+ACE_RCSID(ace, TTY_IO, "TTY_IO.cpp,v 4.18 1999/06/02 21:20:14 nanbor Exp")
+
+// Interface for reading/writing serial device parameters
+
+int
+ACE_TTY_IO::control (Control_Mode cmd,
+ Serial_Params *arg) const
+{
+#if defined (ACE_HAS_TERM_IOCTLS)
+#if defined(TCGETS)
+ struct termios devpar;
+#elif defined(TCGETA)
+ struct termio devpar;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+ u_long c_iflag;
+ u_long c_oflag;
+ u_long c_cflag;
+ u_long c_lflag;
+ // u_long c_line;
+ u_char ivmin_cc4;
+ u_char ivtime_cc5;
+
+ c_iflag=0;
+ c_oflag=0;
+ c_cflag=0;
+ c_lflag=0;
+ // c_line=0;
+
+ // Get default device parameters.
+
+#if defined (TCGETS)
+ if (this->ACE_IO_SAP::control (TCGETS, (void *) &devpar) == -1)
+#elif defined (TCGETA)
+ if (this->ACE_IO_SAP::control (TCGETA, (void *) &devpar) == -1)
+#else
+ errno = ENOSYS;
+#endif /* TCGETS */
+ return -1;
+
+ u_int newbaudrate = 0;
+
+ switch (cmd)
+ {
+ case SETPARAMS:
+ switch (arg->baudrate)
+ {
+ case 300:
+ newbaudrate = B300;
+ break;
+ case 600:
+ newbaudrate = B600;
+ break;
+ case 1200:
+ newbaudrate = B1200;
+ break;
+ case 2400:
+ newbaudrate = B2400;
+ break;
+ case 4800:
+ newbaudrate = B4800;
+ break;
+ case 9600:
+ newbaudrate = B9600;
+ break;
+ case 19200:
+ newbaudrate = B19200;
+ break;
+ case 38400:
+ newbaudrate = B38400;
+ break;
+#if defined (ACE_USES_HIGH_BAUD_RATES)
+// case 56000:
+// newbaudrate = B56000;
+// break;
+ case 57600:
+ newbaudrate = B57600;
+ break;
+ case 115200:
+ newbaudrate = B115200;
+ break;
+// case 128000:
+// newbaudrate = B128000;
+// break;
+// case 256000:
+// newbaudrate = B256000;
+// break;
+#endif /* ACE_USES_HIGH_BAUD_RATES */
+ default:
+ return -1;
+ }
+
+#if defined(ACE_USES_NEW_TERMIOS_STRUCT)
+ // @@ Can you really have different input and output baud
+ // rates?!
+ devpar.c_ispeed = newbaudrate;
+ devpar.c_ospeed = newbaudrate;
+#else
+ c_cflag |= newbaudrate;
+#endif /* ACE_USES_NEW_TERMIOS_STRUCT */
+
+ switch (arg->databits)
+ {
+ case 5:
+ c_cflag |= CS5;
+ break;
+ case 6:
+ c_cflag |= CS6;
+ break;
+ case 7:
+ c_cflag |= CS7;
+ break;
+ case 8:
+ c_cflag |= CS8;
+ break;
+ default:
+ return -1;
+ }
+
+ switch (arg->stopbits)
+ {
+ case 1:
+ break;
+ case 2:
+ c_cflag |= CSTOPB;
+ break;
+ default:
+ return -1;
+ }
+ if (arg->parityenb)
+ {
+ c_cflag |= PARENB;
+ if (ACE_OS::strcmp (arg->paritymode, "ODD") == 0
+ || ACE_OS::strcmp (arg->paritymode, "odd") == 0)
+ c_cflag |= PARODD;
+ }
+
+#if defined (CRTSCTS)
+ // 6/22/00 MLS add rtsenb to if statement
+ if ((arg->ctsenb)||(arg->rtsenb)) /* enable CTS/RTS protocoll */
+ c_cflag |= CRTSCTS;
+#endif /* CRTSCTS */
+#if defined (NEW_RTSCTS)
+ // 8/30/00 MLS add rtsenb to if statement to support new termios
+ if ((arg->ctsenb)||(arg->rtsenb)) /* enable CTS/RTS protocoll */
+ c_cflag |= NEW_RTSCTS;
+#endif /* CRTSCTS */
+#if defined (CREAD)
+ if (arg->rcvenb) /* enable receiver */
+ c_cflag |= CREAD;
+#endif /* CREAD */
+
+
+#if defined (HUPCL)
+ // Cause DTR to be drop after port close MS 7/24/2000;
+ c_cflag |= HUPCL;
+#endif /* HUPCL */
+
+#if defined (CLOCAL)
+ // if device is not a modem set to local device MS 7/24/2000
+ if(!arg->modem)
+ c_cflag |= CLOCAL;
+#endif /* CLOCAL */
+
+ c_oflag = 0;
+ c_iflag = IGNPAR | INPCK;
+ if (arg->databits < 8)
+ c_iflag |= ISTRIP;
+#if defined (IGNBRK)
+ // if device is not a modem set to ignore break points MS 7/24/2000
+ if(!arg->modem)
+ c_iflag |= IGNBRK;
+#endif /* IGNBRK */
+ // 6/22/00 MLS add enable xon/xoff
+#if defined (IXON)
+ if (arg->xinenb) /* enable XON/XOFF output*/
+ c_iflag |= IXON;
+#endif /* IXON */
+#if defined (IXOFF)
+ if (arg->xoutenb) /* enable XON/XOFF input*/
+ c_iflag |= IXOFF;
+#endif /* IXOFF */
+ c_lflag = 0;
+
+ ivmin_cc4 = (u_char) 0;
+ ivtime_cc5= (u_char) (arg->readtimeoutmsec / 100);
+ devpar.c_iflag = c_iflag;
+ devpar.c_oflag = c_oflag;
+ devpar.c_cflag = c_cflag;
+ devpar.c_lflag = c_lflag;
+ devpar.c_cc[ACE_VMIN] = ivmin_cc4;
+ devpar.c_cc[ACE_VTIME] = ivtime_cc5;
+
+#if defined(TIOCMGET)
+ // ensure DTR is enabled
+ int status;
+ this->ACE_IO_SAP::control(TIOCMGET, &status);
+ status |= TIOCM_DTR;
+ this->ACE_IO_SAP::control(TIOCMSET,&status);
+#endif /* definded (TIOCMGET) */
+
+#if defined(TCSETS)
+ return this->ACE_IO_SAP::control (TCSETS,
+ (void *) &devpar);
+#elif defined(TCSETA)
+ return this->ACE_IO_SAP::control (TCSETA,
+ (void *) &devpar);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+ case GETPARAMS:
+ return -1; // Not yet implemented.
+ default:
+ return -1; // Wrong cmd.
+ }
+#elif defined (ACE_WIN32)
+ switch (cmd)
+ {
+ case SETPARAMS:
+ DCB dcb;
+ dcb.DCBlength = sizeof dcb;
+ if (!::GetCommState (this->get_handle (), &dcb))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+/*SadreevAA
+ switch (arg->baudrate)
+ {
+ case 300: dcb.BaudRate = CBR_300; break;
+ case 600: dcb.BaudRate = CBR_600; break;
+ case 1200: dcb.BaudRate = CBR_1200; break;
+ case 2400: dcb.BaudRate = CBR_2400; break;
+ case 4800: dcb.BaudRate = CBR_4800; break;
+ case 9600: dcb.BaudRate = CBR_9600; break;
+ case 19200: dcb.BaudRate = CBR_19200; break;
+ case 38400: dcb.BaudRate = CBR_38400; break;
+// case 56000: dcb.BaudRate = CBR_56000; break;
+ case 57600: dcb.BaudRate = CBR_57600; break;
+ case 115200: dcb.BaudRate = CBR_115200; break;
+// case 128000: dcb.BaudRate = CBR_128000; break;
+// case 256000: dcb.BaudRate = CBR_256000; break;
+ default: return -1;
+ }
+*/
+ dcb.BaudRate = arg->baudrate;
+ switch (arg->databits)
+ {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ dcb.ByteSize = u_char (arg->databits);
+ break;
+ default:
+ return -1;
+ }
+
+ switch (arg->stopbits)
+ {
+ case 1:
+ dcb.StopBits = ONESTOPBIT;
+ break;
+ case 2:
+ dcb.StopBits = TWOSTOPBITS;
+ break;
+ default:
+ return -1;
+ }
+
+
+ // 6/22/00 MLS enabled extra paths for win32 parity checking.
+ if (arg->parityenb)
+ {
+ dcb.fParity = TRUE;
+ if (ACE_OS::strcmp (arg->paritymode, "ODD") == 0
+ || ACE_OS::strcmp (arg->paritymode, "odd") == 0)
+ dcb.Parity = ODDPARITY;
+ else if (ACE_OS::strcmp (arg->paritymode, "EVEN") == 0
+ || ACE_OS::strcmp (arg->paritymode, "even") == 0)
+ dcb.Parity = EVENPARITY;
+ else if (ACE_OS::strcmp (arg->paritymode, "MARK") == 0
+ || ACE_OS::strcmp (arg->paritymode, "mark") == 0)
+ dcb.Parity = MARKPARITY;
+ else if (ACE_OS::strcmp (arg->paritymode, "SPACE") == 0
+ || ACE_OS::strcmp (arg->paritymode, "space") == 0)
+ dcb.Parity = SPACEPARITY;
+ else
+ dcb.Parity = NOPARITY;
+ }
+ else
+ {
+ dcb.fParity = FALSE;
+ dcb.Parity = NOPARITY;
+ }
+
+ if (arg->ctsenb) // enable CTS protocol.
+ dcb.fOutxCtsFlow = TRUE;
+ else
+ dcb.fOutxCtsFlow = FALSE;
+
+ // SadreevAA
+ if (arg->dsrenb) // enable DSR protocol.
+ dcb.fOutxDsrFlow = TRUE;
+ else
+ dcb.fOutxDsrFlow = FALSE;
+
+ // 6/22/00 MLS add great flexibility for win32
+ // pulled rts out of ctsenb
+ switch (arg->rtsenb) // enable RTS protocol.
+ {
+ case 1:
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
+ break;
+ case 2:
+ dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+ break;
+ case 3:
+ dcb.fRtsControl = RTS_CONTROL_TOGGLE;
+ break;
+ default:
+ dcb.fRtsControl = RTS_CONTROL_DISABLE;
+ }
+
+ // 6/22/00 MLS add enable xon/xoff
+ if (arg->xinenb) // enable XON/XOFF for reception
+ dcb.fInX = TRUE; // Fixed by SadreevAA
+ else
+ dcb.fInX = FALSE; // Fixed by SadreevAA
+
+ if (arg->xoutenb) // enable XON/XOFF for transmission
+ dcb.fOutX = TRUE;
+ else
+ dcb.fOutX = FALSE;
+
+ // always set limits unless set to -1 to use default
+ // 6/22/00 MLS add xon/xoff limits
+ if (arg->xonlim != -1)
+ dcb.XonLim = arg->xonlim;
+ if (arg->xofflim != -1)
+ dcb.XoffLim = arg->xofflim;
+
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+ dcb.fAbortOnError = FALSE;
+ dcb.fErrorChar = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fBinary = TRUE;
+ if (!::SetCommState (this->get_handle (), &dcb))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+
+ // 2/13/97 BWF added drop out timer
+ // modified time out to operate correctly with when delay
+ // is requested or no delay is requestes
+ COMMTIMEOUTS timeouts;
+ if (!::GetCommTimeouts (this->get_handle(), &timeouts))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+
+ if (arg->readtimeoutmsec == 0)
+ {
+ // return immediately if no data in the input buffer
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ }
+ else
+ {
+ // Wait for specified time-out for char to arrive
+ // before returning.
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+
+ // ensure specified timeout is below MAXDWORD
+
+ // We don't test arg->readtimeoutmsec against MAXDWORD
+ // directly to avoid a warning in the case DWORD is
+ // unsigned. Ensure specified timeout is below MAXDWORD use
+ // MAXDWORD as indicator for infinite timeout.
+ DWORD dw = arg->readtimeoutmsec;
+ if (dw < MAXDWORD)
+ {
+ // Wait for specified time-out for char to arrive before
+ // returning.
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = dw;
+ }
+ else
+ {
+ // settings for infinite timeout
+ timeouts.ReadIntervalTimeout = 0;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ }
+ }
+
+ if (!::SetCommTimeouts (this->get_handle (), &timeouts))
+ {
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+
+ return 0;
+
+ case GETPARAMS:
+ ACE_NOTSUP_RETURN (-1); // Not yet implemented.
+ default:
+ return -1; // Wrong cmd.
+
+ } // arg switch
+#else
+ ACE_UNUSED_ARG (cmd);
+ ACE_UNUSED_ARG (arg);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_HAS_TERM_IOCTLS */
+}
+
+#if defined (ACE_NEEDS_DEV_IO_CONVERSION)
+ACE_TTY_IO::operator ACE_DEV_IO &()
+{
+ return (ACE_DEV_IO &) *this;
+}
+#endif /* ACE_NEEDS_DEV_IO_CONVERSION */
diff --git a/ace/IPC/TTY_IO.h b/ace/IPC/TTY_IO.h
new file mode 100644
index 00000000000..0f0bdc1b2fb
--- /dev/null
+++ b/ace/IPC/TTY_IO.h
@@ -0,0 +1,84 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TTY_IO.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TTY_IO_H
+#define ACE_TTY_IO_H
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/DEV_Addr.h"
+#include "ace/DEV_Connector.h"
+#include "ace/DEV_IO.h"
+
+/**
+ * @class ACE_TTY_IO
+ *
+ * @brief Class definitions for platform specific TTY features.
+ *
+ * This class represents an example interface for a specific
+ * device (a serial line) It extends the capability of the
+ * underlying DEV_IO class by adding a control method that takes
+ * a special structure (Serial_Params) as argument to allow a
+ * comfortable user interface (away from that annoying termios
+ * structure, which is very specific to UNIX).
+ */
+class ACE_Export ACE_TTY_IO : public ACE_DEV_IO
+{
+public:
+ enum Control_Mode
+ {
+ /// Set control parameters.
+ SETPARAMS,
+ /// Get control parameters.
+ GETPARAMS
+ };
+
+ struct Serial_Params
+ {
+ // Common params
+ int baudrate;
+ int parityenb;
+ const char *paritymode;
+ int databits;
+ int stopbits;
+ int readtimeoutmsec;
+ int ctsenb; // CTS & RTS are the same under unix
+ int rtsenb; // enable & set rts mode (win32)
+ int xinenb; // enable xon/xoff reception
+ int xoutenb; // enable xon/xoff transmission
+
+ // Posix - unix variant
+ int modem;
+ int rcvenb;
+
+ //Win32
+ int dsrenb; // SadreevAA
+
+ int xonlim; // min bytes in input buffer before xon
+ int xofflim; // max bytes in input buffer before xoff
+ };
+
+ /// Interface for reading/writing serial device parameters.
+ int control (Control_Mode cmd,
+ Serial_Params *arg) const;
+
+#if defined (ACE_NEEDS_DEV_IO_CONVERSION)
+ /// This is necessary to pass ACE_TTY_IO as parameter to DEV_Connector.
+ operator ACE_DEV_IO &();
+#endif /* ACE_NEEDS_DEV_IO_CONVERSION */
+};
+
+#endif /* ACE_TTY_IO_H */
diff --git a/ace/IPC/UNIX_Addr.cpp b/ace/IPC/UNIX_Addr.cpp
new file mode 100644
index 00000000000..5b580cff1ce
--- /dev/null
+++ b/ace/IPC/UNIX_Addr.cpp
@@ -0,0 +1,114 @@
+// UNIX_Addr.cpp
+// $Id$
+
+#include "ace/UNIX_Addr.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UNIX_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, UNIX_Addr, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UNIX_Addr)
+
+// Set a pointer to the address.
+void
+ACE_UNIX_Addr::set_addr (void *addr, int len)
+{
+ ACE_TRACE ("ACE_UNIX_Addr::set_addr");
+
+ this->ACE_Addr::base_set (AF_UNIX, len);
+ ACE_OS::memcpy ((void *) &this->unix_addr_,
+ (void *) addr,
+ len);
+}
+
+void
+ACE_UNIX_Addr::dump (void) const
+{
+}
+
+// Do nothing constructor.
+
+ACE_UNIX_Addr::ACE_UNIX_Addr (void)
+ : ACE_Addr (AF_UNIX, sizeof this->unix_addr_)
+{
+ (void) ACE_OS::memset ((void *) &this->unix_addr_,
+ 0,
+ sizeof this->unix_addr_);
+
+ this->unix_addr_.sun_family = AF_UNIX;
+}
+
+int
+ACE_UNIX_Addr::set (const ACE_UNIX_Addr &sa)
+{
+ if (sa.get_type () == AF_ANY)
+ (void) ACE_OS::memset ((void *) &this->unix_addr_,
+ 0,
+ sizeof this->unix_addr_);
+ else
+ ACE_OS::strcpy (this->unix_addr_.sun_path,
+ sa.unix_addr_.sun_path);
+
+ this->unix_addr_.sun_family = AF_UNIX;
+ this->base_set (sa.get_type (), sa.get_size ());
+
+ return 0;
+}
+
+// Copy constructor.
+
+ACE_UNIX_Addr::ACE_UNIX_Addr (const ACE_UNIX_Addr &sa)
+ : ACE_Addr (AF_UNIX, sa.get_size ())
+{
+ this->set (sa);
+}
+
+int
+ACE_UNIX_Addr::set (const sockaddr_un *un, int len)
+{
+ (void) ACE_OS::memset ((void *) &this->unix_addr_, 0,
+ sizeof this->unix_addr_);
+ this->unix_addr_.sun_family = AF_UNIX;
+ ACE_OS::strcpy (this->unix_addr_.sun_path, un->sun_path);
+ this->base_set (AF_UNIX, len);
+ return 0;
+}
+
+ACE_UNIX_Addr::ACE_UNIX_Addr (const sockaddr_un *un, int len)
+{
+ this->set (un, len);
+}
+
+int
+ACE_UNIX_Addr::set (const char rendezvous_point[])
+{
+ (void) ACE_OS::memset ((void *) &this->unix_addr_,
+ 0,
+ sizeof this->unix_addr_);
+ this->unix_addr_.sun_family = AF_UNIX;
+ size_t len = ACE_OS::strlen (rendezvous_point);
+ size_t maxlen = sizeof this->unix_addr_.sun_path;
+
+ (void) ACE_OS::memcpy (this->unix_addr_.sun_path,
+ rendezvous_point,
+ len >= maxlen ? maxlen - 1 : len);
+
+ this->ACE_Addr::base_set (AF_UNIX,
+ sizeof this->unix_addr_ -
+ sizeof (this->unix_addr_.sun_path) +
+ ACE_OS::strlen (this->unix_addr_.sun_path));
+ return 0;
+}
+
+// Create a ACE_Addr from a UNIX pathname.
+
+ACE_UNIX_Addr::ACE_UNIX_Addr (const char rendezvous_point[])
+{
+ this->set (rendezvous_point);
+}
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/IPC/UNIX_Addr.h b/ace/IPC/UNIX_Addr.h
new file mode 100644
index 00000000000..fc9be3bdff6
--- /dev/null
+++ b/ace/IPC/UNIX_Addr.h
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file UNIX_Addr.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_UNIX_ADDR_H
+#define ACE_UNIX_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_UNIX_Addr
+ *
+ * @brief Defines the ``UNIX domain address family'' address format.
+ */
+class ACE_Export ACE_UNIX_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_UNIX_Addr (void);
+
+ /// Copy constructor.
+ ACE_UNIX_Addr (const ACE_UNIX_Addr &sa);
+
+ /// Creates an ACE_UNIX_Addr from a string.
+ ACE_UNIX_Addr (const char rendezvous_point[]);
+
+ /// Creates an ACE_INET_Addr from a sockaddr_un structure.
+ ACE_UNIX_Addr (const sockaddr_un *, int len);
+
+ /// Creates an ACE_UNIX_Addr from another <ACE_UNIX_Addr>.
+ int set (const ACE_UNIX_Addr &sa);
+
+ /// Creates an ACE_UNIX_Addr from a string.
+ int set (const char rendezvous_point[]);
+
+ /// Creates an ACE_UNIX_Addr from a sockaddr_un structure.
+ int set (const sockaddr_un *, int len);
+
+ /// Return a pointer to the underlying network address.
+ virtual void *get_addr (void) const;
+
+ /// Set a pointer to the underlying network address.
+ virtual void set_addr (void *addr, int len);
+
+ /// Transform the current address into string format.
+ virtual int addr_to_string (char addr[], size_t) const;
+
+ /// Transform the string into the current addressing format.
+ virtual int string_to_addr (const char addr[]);
+
+ /// Compare two addresses for equality.
+ int operator == (const ACE_UNIX_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ int operator != (const ACE_UNIX_Addr &SAP) const;
+
+ /// Return the path name of the underlying rendezvous point.
+ const char *get_path_name (void) const;
+
+ /// Computes and returns hash value.
+ virtual u_long hash (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Underlying socket address.
+ sockaddr_un unix_addr_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/UNIX_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_UNIX_ADDR_H */
diff --git a/ace/IPC/UNIX_Addr.i b/ace/IPC/UNIX_Addr.i
new file mode 100644
index 00000000000..2ef10e67556
--- /dev/null
+++ b/ace/IPC/UNIX_Addr.i
@@ -0,0 +1,67 @@
+/* -*- C++ -*- */
+// $Id$
+
+// UNIX_Addr.i
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// Return a pointer to the underlying address.
+
+ACE_INLINE void *
+ACE_UNIX_Addr::get_addr (void) const
+{
+ return (void *) &this->unix_addr_;
+}
+
+// Transform the string into the current addressing format.
+
+ACE_INLINE int
+ACE_UNIX_Addr::string_to_addr (const char addr[])
+{
+ ACE_OS::strsncpy (this->unix_addr_.sun_path, addr,
+ sizeof this->unix_addr_.sun_path);
+ return 0;
+}
+
+// Transform the current address into string format.
+
+ACE_INLINE int
+ACE_UNIX_Addr::addr_to_string (char s[], size_t len) const
+{
+ ACE_OS::strsncpy (s, this->unix_addr_.sun_path, len);
+ return 0;
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE int
+ACE_UNIX_Addr::operator == (const ACE_UNIX_Addr &sap) const
+{
+ return ACE_OS::strncmp (this->unix_addr_.sun_path,
+ sap.unix_addr_.sun_path,
+ sizeof this->unix_addr_.sun_path) == 0;
+}
+
+// Compare two addresses for inequality.
+
+ACE_INLINE int
+ACE_UNIX_Addr::operator != (const ACE_UNIX_Addr &sap) const
+{
+ return !((*this) == sap); // This is lazy, of course... ;-)
+}
+
+// Return the path name used for the rendezvous point.
+
+ACE_INLINE const char *
+ACE_UNIX_Addr::get_path_name (void) const
+{
+ return this->unix_addr_.sun_path;
+}
+
+ACE_INLINE u_long
+ACE_UNIX_Addr::hash (void) const
+{
+ return ACE::hash_pjw (this->unix_addr_.sun_path);
+}
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/IPC/UPIPE_Acceptor.cpp b/ace/IPC/UPIPE_Acceptor.cpp
new file mode 100644
index 00000000000..379155616f3
--- /dev/null
+++ b/ace/IPC/UPIPE_Acceptor.cpp
@@ -0,0 +1,122 @@
+// UPIPE_Acceptor.cpp
+// $Id$
+
+#include "ace/UPIPE_Acceptor.h"
+
+ACE_RCSID(ace, UPIPE_Acceptor, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/UPIPE_Acceptor.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Acceptor)
+
+void
+ACE_UPIPE_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::dump");
+}
+
+/* Do nothing routine for constructor. */
+
+ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor (void)
+ : mb_ (sizeof (ACE_UPIPE_Stream *))
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor");
+}
+
+ACE_UPIPE_Acceptor::~ACE_UPIPE_Acceptor (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::~ACE_UPIPE_Acceptor");
+}
+
+// General purpose routine for performing server ACE_UPIPE.
+
+int
+ACE_UPIPE_Acceptor::open (const ACE_UPIPE_Addr &local_addr,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::open");
+ return this->ACE_SPIPE_Acceptor::open (local_addr, reuse_addr);
+}
+
+int
+ACE_UPIPE_Acceptor::close (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::close");
+ return this->ACE_SPIPE_Acceptor::close ();
+}
+
+// General purpose routine for accepting new connections.
+
+ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor (const ACE_UPIPE_Addr &local_addr,
+ int reuse_addr)
+ : mb_ (sizeof (ACE_UPIPE_Stream *))
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor");
+
+ if (this->open (local_addr, reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_UPIPE_Acceptor")));
+}
+
+int
+ACE_UPIPE_Acceptor::accept (ACE_UPIPE_Stream &new_stream,
+ ACE_UPIPE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::accept");
+ ACE_UNUSED_ARG (reset_new_handle);
+
+ ACE_SPIPE_Stream new_io;
+
+ if (this->ACE_SPIPE_Acceptor::accept (new_io, remote_addr,
+ timeout, restart) == -1)
+ return -1;
+ else
+ {
+ ACE_UPIPE_Stream *remote_stream = 0;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, new_stream.lock_, -1));
+
+ new_stream.set_handle (new_io.get_handle ());
+ new_stream.reference_count_++;
+
+ // Transfer address ownership.
+ new_io.get_local_addr (new_stream.local_addr_);
+ new_io.get_remote_addr (new_stream.remote_addr_);
+
+ // Now that we got the handle, we'll read the address of the
+ // connector-side ACE_UPIPE_Stream out of the pipe and link that
+ // ACE_UPIPE_Stream to our ACE_UPIPE_Stream.
+
+ if (ACE_OS::read (new_stream.get_handle (),
+ (char *) &remote_stream,
+ sizeof remote_stream) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_LIB_TEXT ("read stream address failed")));
+ else if (new_stream.stream_.link (remote_stream->stream_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_LIB_TEXT ("link streams failed")));
+ // Send a message over the new streampipe to confirm acceptance.
+ else if (new_stream.send (&mb_, 0) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_UPIPE_Acceptor: %p\n"),
+ ACE_LIB_TEXT ("linked stream.put failed")));
+
+ // Close down the new_stream at this point in order to conserve
+ // handles. Note that we don't need the SPIPE connection
+ // anymore since we're now linked via the <Message_Queue>.
+ new_stream.ACE_SPIPE::close ();
+ return 0;
+ }
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ace/IPC/UPIPE_Acceptor.h b/ace/IPC/UPIPE_Acceptor.h
new file mode 100644
index 00000000000..d19151370fc
--- /dev/null
+++ b/ace/IPC/UPIPE_Acceptor.h
@@ -0,0 +1,94 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file UPIPE_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_UPIPE_ACCEPTOR_H
+#define ACE_UPIPE_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/UPIPE_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Thread_Manager.h"
+
+#if defined (ACE_HAS_THREADS)
+
+/**
+ * @class ACE_UPIPE_Acceptor
+ *
+ * @brief Defines the format and interface for the listener side of the
+ * ACE_UPIPE_Stream.
+ */
+class ACE_Export ACE_UPIPE_Acceptor : public ACE_SPIPE_Acceptor
+{
+public:
+ // = Initialization and termination.
+ /// Default constructor.
+ ACE_UPIPE_Acceptor (void);
+
+ /// Initialize passive endpoint.
+ ACE_UPIPE_Acceptor (const ACE_UPIPE_Addr &local_sap,
+ int reuse_addr = 0);
+
+ /// Initialize passive endpoint.
+ int open (const ACE_UPIPE_Addr &local_sap,
+ int reuse_addr = 0);
+
+ /// Close down and release resources.
+ ~ACE_UPIPE_Acceptor (void);
+
+ /// Close down and release resources.
+ int close (void);
+
+ /// Close down and release resources and remove the underlying SPIPE
+ /// rendezvous point.
+ int remove (void);
+
+ // = Passive connection acceptance method.
+ /**
+ * Accept a new data transfer connection. A <timeout> of 0 means
+ * block forever, a <timeout> of {0, 0} means poll. <restart> == 1
+ * means "restart if interrupted."
+ */
+ int accept (ACE_UPIPE_Stream &server_stream,
+ ACE_UPIPE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Manage threads.
+ ACE_Thread_Manager tm;
+
+ /// To confirm connection establishment.
+ ACE_Message_Block mb_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/UPIPE_Acceptor.i"
+#endif
+
+#endif /* ACE_HAS_THREADS */
+#include "ace/post.h"
+#endif /* ACE_UPIPE_ACCEPTOR_H */
diff --git a/ace/IPC/UPIPE_Acceptor.i b/ace/IPC/UPIPE_Acceptor.i
new file mode 100644
index 00000000000..d47cf593242
--- /dev/null
+++ b/ace/IPC/UPIPE_Acceptor.i
@@ -0,0 +1,11 @@
+/* -*- C++ -*- */
+// $Id$
+
+// UPIPE_Acceptor.i
+
+ASYS_INLINE int
+ACE_UPIPE_Acceptor::remove (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Acceptor::remove");
+ return this->ACE_SPIPE_Acceptor::remove ();
+}
diff --git a/ace/IPC/UPIPE_Addr.h b/ace/IPC/UPIPE_Addr.h
new file mode 100644
index 00000000000..1a46f564403
--- /dev/null
+++ b/ace/IPC/UPIPE_Addr.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+
+
+//=============================================================================
+/**
+ * @file UPIPE_Addr.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_UPIPE_ADDR_H
+#define ACE_UPIPE_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/SPIPE_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+typedef ACE_SPIPE_Addr ACE_UPIPE_Addr;
+
+#if 0
+// We need this "class" to make the class2man documentation utility
+// happy.
+/**
+ * @class ACE_UPIPE_Addr
+ *
+ * @brief Defines the ACE "user pipe" address family address format.
+ *
+ * This class has an identical interface to the <ACE_SPIPE_Addr>
+ * class. In fact, it's simply a typedef!
+ */
+class ACE_Export ACE_UPIPE_Addr
+{
+public:
+ // = Same interface as <ACE_SPIPE_Addr>.
+};
+#endif /* 0 */
+#include "ace/post.h"
+#endif /* ACE_UPIPE_ADDR_H */
diff --git a/ace/IPC/UPIPE_Connector.cpp b/ace/IPC/UPIPE_Connector.cpp
new file mode 100644
index 00000000000..d2edc143a50
--- /dev/null
+++ b/ace/IPC/UPIPE_Connector.cpp
@@ -0,0 +1,91 @@
+// UPIPE_Connector.cpp
+// $Id$
+
+#include "ace/UPIPE_Connector.h"
+
+ACE_RCSID(ace, UPIPE_Connector, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/UPIPE_Connector.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Connector)
+
+void
+ACE_UPIPE_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_UPIPE_Connector::dump");
+}
+
+ACE_UPIPE_Connector::ACE_UPIPE_Connector (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Connector::ACE_UPIPE_Connector");
+}
+
+int
+ACE_UPIPE_Connector::connect (ACE_UPIPE_Stream &new_stream,
+ const ACE_UPIPE_Addr &addr,
+ ACE_Time_Value *timeout,
+ const ACE_Addr & /* local_sap */,
+ int /* reuse_addr */,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_UPIPE_Connector::connect");
+ ACE_ASSERT (new_stream.get_handle () == ACE_INVALID_HANDLE);
+
+ ACE_HANDLE handle = ACE_Handle_Ops::handle_timed_open (timeout,
+ addr.get_path_name (),
+ flags, perms);
+
+ if (handle == ACE_INVALID_HANDLE)
+ return -1;
+#if !defined (ACE_WIN32)
+ else if (ACE_OS::isastream (handle) != 1)
+ return -1;
+#endif
+ else // We're connected!
+ {
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, new_stream.lock_, -1));
+
+ ACE_UPIPE_Stream *ustream = &new_stream;
+
+ new_stream.set_handle (handle);
+ new_stream.remote_addr_ = addr; // class copy.
+ new_stream.reference_count_++;
+
+ // Now send the address of our ACE_UPIPE_Stream over this pipe
+ // to our corresponding ACE_UPIPE_Acceptor, so he may link the
+ // two streams.
+ ssize_t result = ACE_OS::write (handle,
+ (const char *) &ustream,
+ sizeof ustream);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_UPIPE_Connector %p\n"),
+ ACE_LIB_TEXT ("write to pipe failed")));
+
+ // Wait for confirmation of stream linking.
+ ACE_Message_Block *mb_p = 0;
+
+ // Our part is done, wait for server to confirm connection.
+ result = new_stream.recv (mb_p, 0);
+
+ // Do *not* coalesce the following two checks for result == -1.
+ // They perform different checks and cannot be merged.
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_UPIPE_Connector %p\n"),
+ ACE_LIB_TEXT ("no confirmation from server")));
+ else
+ // Close down the new_stream at this point in order to
+ // conserve handles. Note that we don't need the SPIPE
+ // connection anymore since we're linked via the Message_Queue
+ // now.
+ new_stream.ACE_SPIPE::close ();
+ return result;
+ }
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ace/IPC/UPIPE_Connector.h b/ace/IPC/UPIPE_Connector.h
new file mode 100644
index 00000000000..82053fd59a2
--- /dev/null
+++ b/ace/IPC/UPIPE_Connector.h
@@ -0,0 +1,112 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file UPIPE_Connector.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer and Douglas C. Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_UPIPE_CONNECTOR_H
+#define ACE_UPIPE_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/UPIPE_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/SPIPE_Stream.h"
+
+#if defined (ACE_HAS_THREADS)
+
+/**
+ * @class ACE_UPIPE_Connector
+ *
+ * @brief Defines an active connection factory for the
+ * <ACE_UPIPE_STREAM> wrappers.
+ */
+class ACE_Export ACE_UPIPE_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_UPIPE_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ ACE_UPIPE_Connector (ACE_UPIPE_Stream &new_stream,
+ const ACE_UPIPE_Addr &addr,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <flags> and <perms> arguments are passed down to the <open>
+ * method.
+ */
+ int connect (ACE_UPIPE_Stream &new_stream,
+ const ACE_UPIPE_Addr &addr,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ // = Meta-type info
+ typedef ACE_UPIPE_Addr PEER_ADDR;
+ typedef ACE_UPIPE_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/UPIPE_Connector.i"
+#endif
+
+#endif /* ACE_HAS_THREADS */
+#include "ace/post.h"
+#endif /* ACE_UPIPE_CONNECTOR_H */
diff --git a/ace/IPC/UPIPE_Connector.i b/ace/IPC/UPIPE_Connector.i
new file mode 100644
index 00000000000..a8a68342e77
--- /dev/null
+++ b/ace/IPC/UPIPE_Connector.i
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+// $Id$
+
+// UPIPE_Connector.i
+
+// Creates a Local ACE_UPIPE.
+
+ASYS_INLINE
+ACE_UPIPE_Connector::ACE_UPIPE_Connector (ACE_UPIPE_Stream &new_stream,
+ const ACE_UPIPE_Addr &addr,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE_UPIPE_Connector::ACE_UPIPE_Connector");
+ if (this->connect (new_stream, addr, timeout, local_sap,
+ reuse_addr, flags, perms) == -1
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("address %s, %p\n"),
+ addr.get_path_name (),
+ ACE_LIB_TEXT ("ACE_UPIPE_Connector")));
+}
+
+ASYS_INLINE int
+ACE_UPIPE_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+ ACE_UNUSED_ARG (handle);
+ // Nothing to do here since the handle is not a socket
+ return 0;
+}
diff --git a/ace/IPC/UPIPE_Stream.cpp b/ace/IPC/UPIPE_Stream.cpp
new file mode 100644
index 00000000000..dd1aca73cc3
--- /dev/null
+++ b/ace/IPC/UPIPE_Stream.cpp
@@ -0,0 +1,227 @@
+// UPIPE_Stream.cpp
+// $Id$
+
+#include "ace/UPIPE_Stream.h"
+
+ACE_RCSID(ace, UPIPE_Stream, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/UPIPE_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+
+ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Stream)
+
+ACE_UPIPE_Stream::ACE_UPIPE_Stream (void)
+ : mb_last_ (0),
+ remaining_ (0),
+ reference_count_ (0)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::ACE_UPIPE_STREAM");
+}
+
+ACE_UPIPE_Stream::~ACE_UPIPE_Stream (void)
+{
+ if (this->mb_last_ != 0)
+ this->mb_last_->release ();
+}
+
+int
+ACE_UPIPE_Stream::control (int cmd,
+ void * val) const
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::control");
+
+ return ((ACE_UPIPE_Stream *) this)->stream_.control
+ ((ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds) cmd, val);
+}
+
+void
+ACE_UPIPE_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::dump");
+}
+
+int
+ACE_UPIPE_Stream::close (void)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::close");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ this->reference_count_--;
+
+ if (this->reference_count_ == 0)
+ {
+ // Since the UPIPE should have been closed earlier we won't bother
+ // checking to see if closing it now fails.
+
+ if (this->ACE_SPIPE::get_handle () != ACE_INVALID_HANDLE)
+ this->ACE_SPIPE::close ();
+
+ // Close down the ACE_stream.
+ return this->stream_.close ();
+ }
+ return 0;
+}
+
+int
+ACE_UPIPE_Stream::get_remote_addr (ACE_UPIPE_Addr &remote_sap) const
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::get_remote_addr");
+ remote_sap = this->remote_addr_;
+ return 0;
+}
+
+int
+ACE_UPIPE_Stream::send (ACE_Message_Block *mb_p,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::send_msg");
+ return this->stream_.put (mb_p, timeout) == -1 ? -1 : 0;
+}
+
+int ACE_UPIPE_Stream::recv (ACE_Message_Block *& mb_p,
+ ACE_Time_Value *timeout)
+{
+ return this->stream_.get (mb_p, timeout) == -1 ? -1 : 0;
+}
+
+// Send a buffer.
+
+int
+ACE_UPIPE_Stream::send (const char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::send");
+
+ ACE_Message_Block *mb_p;
+ ACE_NEW_RETURN (mb_p,
+ ACE_Message_Block (n),
+ -1);
+ mb_p->copy (buffer, n);
+ return this->stream_.put (mb_p, timeout) == -1 ? -1 : (int) n;
+}
+
+// Receive a buffer.
+
+int
+ACE_UPIPE_Stream::recv (char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::recv");
+ // Index in buffer.
+ size_t bytes_read = 0;
+
+ while (bytes_read < n)
+ if (this->mb_last_ != 0)
+ {
+ // We have remaining data in our last read Message_Buffer.
+
+ if (this->remaining_ < n)
+ {
+ // The remaining data is not enough.
+
+ ACE_OS::memcpy ((void *) &buffer[bytes_read],
+ this->mb_last_->rd_ptr (),
+ this->remaining_);
+ bytes_read += this->remaining_;
+ this->remaining_ = 0;
+ this->mb_last_ = this->mb_last_->release ();
+ return bytes_read;
+ }
+ else
+ {
+ // The remaining data is at least enough. If there's
+ // more, we'll get it the next time through.
+
+ ACE_OS::memcpy (&buffer[bytes_read],
+ this->mb_last_->rd_ptr (),
+ n);
+ bytes_read += n;
+
+ // Advance rd_ptr.
+ this->mb_last_->rd_ptr (n);
+ this->remaining_ -= n;
+
+ if (this->remaining_ == 0)
+ // Now the Message_Buffer is empty.
+
+ this->mb_last_ = this->mb_last_->release ();
+ }
+ }
+ else
+ {
+ // We have to get a new Message_Buffer from our stream.
+
+ int result = this->stream_.get (this->mb_last_, timeout);
+
+ if (result == -1)
+ {
+ if (errno == EWOULDBLOCK && bytes_read > 0)
+ // Return the number of bytes read before we timed out.
+ return bytes_read;
+ else
+ return -1;
+ }
+ this->remaining_ = this->mb_last_->size ();
+ }
+
+ return bytes_read;
+}
+
+int
+ACE_UPIPE_Stream::send_n (const char *buf,
+ size_t n,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::send_n");
+
+ size_t bytes_written;
+ ssize_t len = 0;
+
+ for (bytes_written = 0;
+ bytes_written < n;
+ bytes_written += len)
+ {
+ len = this->send (buf + bytes_written,
+ n - bytes_written,
+ timeout);
+
+ if (len == -1)
+ return -1;
+ }
+
+ return bytes_written;
+}
+
+int
+ACE_UPIPE_Stream::recv_n (char *buf,
+ size_t n,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::recv_n");
+ size_t bytes_read;
+ ssize_t len = 0;
+
+ for (bytes_read = 0;
+ bytes_read < n;
+ bytes_read += len)
+ {
+ len = this->recv (buf + bytes_read,
+ n - bytes_read,
+ timeout);
+ if (len == -1)
+ return -1;
+ else if (len == 0)
+ break;
+ }
+
+ return bytes_read;
+}
+
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ace/IPC/UPIPE_Stream.h b/ace/IPC/UPIPE_Stream.h
new file mode 100644
index 00000000000..8fd79a1c269
--- /dev/null
+++ b/ace/IPC/UPIPE_Stream.h
@@ -0,0 +1,137 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file UPIPE_Stream.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_UPIPE_STREAM_H
+#define ACE_UPIPE_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/SPIPE.h"
+#include "ace/Message_Queue.h"
+#include "ace/UPIPE_Addr.h"
+
+#if defined (ACE_HAS_THREADS)
+
+// Use a typedef to make life easier later on.
+typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+
+/**
+ * @class ACE_UPIPE_Stream
+ *
+ * @brief Defines the method that transfer data on a UPIPE.
+ */
+class ACE_Export ACE_UPIPE_Stream : public ACE_SPIPE
+{
+public:
+ friend class ACE_UPIPE_Acceptor;
+ friend class ACE_UPIPE_Connector;
+
+ // = Initialization and Termination.
+
+ ACE_UPIPE_Stream (void);
+
+ virtual ~ACE_UPIPE_Stream (void);
+
+ /// Shut down the UPIPE and release resources.
+ int close (void);
+
+ /// Return the underlying I/O handle.
+ ACE_HANDLE get_handle (void) const;
+
+ // = Send/recv ACE Message_Blocks.
+ /// Send a message through the message queue. Returns -1 on error,
+ /// else 0.
+ int send (ACE_Message_Block *mb_p,
+ ACE_Time_Value *timeout = 0);
+
+ /// Recv a message from the message queue. Returns -1 on error, else
+ /// 0.
+ int recv (ACE_Message_Block *&mb_p,
+ ACE_Time_Value *timeout = 0);
+
+ // = Send/recv char buffers.
+ /// Send a buffer of <n> bytes through the message queue. Returns -1
+ /// on error, else number of bytes sent.
+ int send (const char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Recv a buffer of upto <n> bytes from the message queue. Returns
+ /// -1 on error, else number of bytes read.
+ int recv (char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Send a buffer of exactly <n> bytes to the message queue. Returns
+ /// -1 on error, else number of bytes written (which should == n).
+ int send_n (const char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Recv a buffer of exactly <n> bytes from the message queue.
+ /// Returns -1 on error, else the number of bytes read.
+ int recv_n (char *buffer,
+ size_t n,
+ ACE_Time_Value *timeout = 0);
+
+ /// Perform control operations on the UPIPE_Stream.
+ int control (int cmd, void *val) const;
+
+ /// Return the remote address we are connected to.
+ int get_remote_addr (ACE_UPIPE_Addr &remote_sap) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// To hold the last ACE_Message_Block read out of the stream. Thus
+ /// allowing subsequent reads from one ACE_Message_Block
+ ACE_Message_Block *mb_last_;
+
+ /// Holds the number of bytes that are still available in mb_last_.
+ size_t remaining_;
+
+ /// Address of who we are connected to.
+ ACE_UPIPE_Addr remote_addr_;
+
+ /// Stream component used by the <UPIPE_Acceptor> and
+ /// <UPIPE_Connector> to link together two UPIPE_Streams.
+ MT_Stream stream_;
+
+ /// Keep track of whether the sender and receiver have both shut
+ /// down.
+ int reference_count_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ /// Ensure that we are thread-safe.
+ ACE_Thread_Mutex lock_;
+#endif /* ACE_MT_SAFE */
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/UPIPE_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+#include "ace/post.h"
+#endif /*ACE_UPIPE_STREAM_H */
diff --git a/ace/IPC/UPIPE_Stream.i b/ace/IPC/UPIPE_Stream.i
new file mode 100644
index 00000000000..c2297fcffce
--- /dev/null
+++ b/ace/IPC/UPIPE_Stream.i
@@ -0,0 +1,12 @@
+/* -*- C++ -*- */
+// $Id$
+
+// UPIPE_Stream.i
+
+ACE_INLINE ACE_HANDLE
+ACE_UPIPE_Stream::get_handle (void) const
+{
+ ACE_TRACE ("ACE_UPIPE_Stream::get_handle");
+ return this->ACE_SPIPE::get_handle ();
+}
+
diff --git a/ace/IPC/XTI_ATM_Mcast.cpp b/ace/IPC/XTI_ATM_Mcast.cpp
new file mode 100644
index 00000000000..0892672635e
--- /dev/null
+++ b/ace/IPC/XTI_ATM_Mcast.cpp
@@ -0,0 +1,66 @@
+// XTI_ATM_Mcast.cpp
+// $Id$
+
+#include "ace/XTI_ATM_Mcast.h"
+
+ACE_RCSID(ace, XTI_ATM_Mcast, "$Id$")
+
+#if defined (ACE_HAS_XTI_ATM)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/XTI_ATM_Mcast.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_ALLOC_HOOK_DEFINE(ACE_XTI_ATM_Mcast)
+
+void
+ACE_XTI_ATM_Mcast::dump (void) const
+{
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::dump");
+}
+
+ACE_XTI_ATM_Mcast::ACE_XTI_ATM_Mcast (void)
+{
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::ACE_XTI_ATM_Mcast");
+}
+
+// Add a leaf to the current connection (i.e., multicast).
+
+int
+ACE_XTI_ATM_Mcast::add_leaf (ACE_TLI_Stream &current_stream,
+ const ACE_Addr &remote_sap,
+ ACE_INT32 leaf_id,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::add_leaf");
+
+ struct netbuf call_req;
+ memset(&call_req, 0, sizeof(call_req));
+ call_req.len = remote_sap.get_size ();
+ call_req.buf = (char *)remote_sap.get_addr ();
+
+ if (::t_addleaf(current_stream.get_handle(),
+ leaf_id,
+ &call_req) < 0)
+ {
+ // Check for asynchronous event
+ if (t_errno == TLOOK)
+ {
+ int event;
+ event = ACE_OS::t_look(current_stream.get_handle());
+ if (event != TNODATA && event != T_DATA)
+ return -1;
+ else
+ // If this doesn't work for asynchronous calls we need to call
+ // the XTI/ATM t_rcvleafchange() function to check for t_addleaf
+ // completion.
+ return complete (current_stream, 0, timeout);
+ }
+ else
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* ACE_HAS_XTI_ATM */
diff --git a/ace/IPC/XTI_ATM_Mcast.h b/ace/IPC/XTI_ATM_Mcast.h
new file mode 100644
index 00000000000..ed1ef058303
--- /dev/null
+++ b/ace/IPC/XTI_ATM_Mcast.h
@@ -0,0 +1,129 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file XTI_ATM_Mcast.h
+ *
+ * $Id$
+ *
+ * @author Joe Hoffert
+ */
+//=============================================================================
+
+
+#ifndef ACE_XTI_ATM_MCAST_H
+#define ACE_XTI_ATM_MCAST_H
+#include "ace/pre.h"
+
+#include "ace/TLI_Connector.h"
+#include "ace/ATM_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_XTI_ATM)
+
+/**
+ * @class ACE_XTI_ATM_Mcast
+ *
+ * @brief Defines an active connection factory for the ACE_TLI C++
+ * wrappers to support XTI/ATM multicast.
+ */
+class ACE_Export ACE_XTI_ATM_Mcast : public ACE_TLI_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_XTI_ATM_Mcast (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ ACE_XTI_ATM_Mcast (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0,
+ const char device[] = ACE_XTI_ATM_DEVICE,
+ struct t_info *info = 0,
+ int rw_flag = 1,
+ struct netbuf *udata = 0,
+ struct netbuf *opt = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = O_RDWR,
+ int perms = 0,
+ const char device[] = ACE_XTI_ATM_DEVICE,
+ struct t_info *info = 0,
+ int rw_flag = 1,
+ struct netbuf *udata = 0,
+ struct netbuf *opt = 0);
+
+ /**
+ * Actively add a leaf to the currently connected stream (i.e.,
+ * multicast). The <remote_sap> is the address of the leaf that we
+ * are trying to add. The <timeout> is the amount of time to wait to
+ * connect. If it's 0 then we block indefinitely. If *timeout ==
+ * {0, 0} then the connection is done using non-blocking mode. In
+ * this case, if the connection can't be made immediately the value
+ * of -1 is returned with <errno == EWOULDBLOCK>. If *timeout >
+ * {0, 0} then this is the amount of time to wait before timing out.
+ * If the time expires before the connection is made <errno == ETIME>.
+ */
+ int add_leaf (ACE_TLI_Stream &current_stream,
+ const ACE_Addr &remote_sap,
+ ACE_INT32 leaf_id,
+ ACE_Time_Value *timeout = 0);
+
+ // = Meta-type info
+ typedef ACE_ATM_Addr PEER_ADDR;
+ typedef ACE_TLI_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/XTI_ATM_Mcast.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_XTI_ATM */
+#include "ace/post.h"
+#endif /* ACE_XTI_ATM_MCAST_H */
diff --git a/ace/IPC/XTI_ATM_Mcast.i b/ace/IPC/XTI_ATM_Mcast.i
new file mode 100644
index 00000000000..2baab539fc8
--- /dev/null
+++ b/ace/IPC/XTI_ATM_Mcast.i
@@ -0,0 +1,62 @@
+/* -*- C++ -*- */
+// $Id$
+
+// XTI_ATM_Mcast.i
+
+ACE_INLINE
+ACE_XTI_ATM_Mcast::ACE_XTI_ATM_Mcast (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ const char device[],
+ struct t_info *info,
+ int rwf,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::ACE_XTI_ATM_Mcast");
+ if (this->connect (new_stream, remote_sap, timeout, local_sap, reuse_addr,
+ flags, perms, device,
+ info, rwf,
+ udata, opt) == ACE_INVALID_HANDLE
+ && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIME))
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_TLI_Stream::ACE_TLI_Stream")));
+}
+
+// Connect the <new_stream> to the <remote_sap>, waiting up to
+// <timeout> amount of time if necessary. This is simple a pass-
+// through function to ACE_TLI_Connector::connect(). It is over-
+// ridden to change the default device from TCP to XTI/ATM.
+
+ACE_INLINE
+int
+ACE_XTI_ATM_Mcast::connect (ACE_TLI_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ const char device[],
+ struct t_info *info,
+ int rw_flag,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_XTI_ATM_Mcast::connect");
+ return ACE_TLI_Connector::connect(new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ device,
+ info,
+ rw_flag,
+ udata,
+ opt);
+}
diff --git a/ace/Logging/Dump.cpp b/ace/Logging/Dump.cpp
new file mode 100644
index 00000000000..52786c00d99
--- /dev/null
+++ b/ace/Logging/Dump.cpp
@@ -0,0 +1,136 @@
+// $Id$
+
+#include "ace/Synch_T.h"
+#include "ace/Dump.h"
+#include "ace/Object_Manager.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Dump, "$Id$")
+
+// Implementations (very simple for now...)
+
+ACE_Dumpable::~ACE_Dumpable (void)
+{
+ ACE_TRACE ("ACE_Dumpable::~ACE_Dumpable");
+}
+
+ACE_Dumpable::ACE_Dumpable (const void *this_ptr)
+ : this_ (this_ptr)
+{
+ ACE_TRACE ("ACE_Dumpable::ACE_Dumpable");
+}
+
+ACE_Dumpable_Ptr::ACE_Dumpable_Ptr (const ACE_Dumpable *dumper)
+ : dumper_ (dumper)
+{
+ ACE_TRACE ("ACE_Dumpable_Ptr::ACE_Dumpable_Ptr");
+}
+
+const ACE_Dumpable *
+ACE_Dumpable_Ptr::operator->() const
+{
+ ACE_TRACE ("ACE_Dumpable_Ptr::operator->");
+ return this->dumper_;
+}
+
+void
+ACE_Dumpable_Ptr::operator= (const ACE_Dumpable *dumper) const
+{
+ ACE_TRACE ("ACE_Dumpable_Ptr::operator=");
+ if (this->dumper_ != dumper)
+ {
+ delete (ACE_Dumpable *) this->dumper_;
+ ((ACE_Dumpable_Ptr *) this)->dumper_ = dumper;
+ }
+}
+
+ACE_ODB::ACE_ODB (void)
+ // Let the Tuple default constructor initialize object_table_
+ : current_size_ (0)
+{
+ ACE_TRACE ("ACE_ODB::ACE_ODB");
+}
+
+ACE_ODB *
+ACE_ODB::instance (void)
+{
+ ACE_TRACE ("ACE_ODB::instance");
+
+ if (ACE_ODB::instance_ == 0)
+ {
+ ACE_MT (ACE_Thread_Mutex *lock =
+ ACE_Managed_Object<ACE_Thread_Mutex>::get_preallocated_object
+ (ACE_Object_Manager::ACE_DUMP_LOCK);
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, *lock, 0));
+
+ if (ACE_ODB::instance_ == 0)
+ ACE_NEW_RETURN (ACE_ODB::instance_,
+ ACE_ODB,
+ 0);
+ }
+
+ return ACE_ODB::instance_;
+}
+
+void
+ACE_ODB::dump_objects (void)
+{
+ ACE_TRACE ("ACE_ODB::dump_objects");
+ for (int i = 0; i < this->current_size_; i++)
+ {
+ if (this->object_table_[i].this_ != 0)
+ // Dump the state of the object.
+ this->object_table_[i].dumper_->dump ();
+ }
+}
+
+// This method registers a new <dumper>. It detects
+// duplicates and simply overwrites them.
+
+void
+ACE_ODB::register_object (const ACE_Dumpable *dumper)
+{
+ ACE_TRACE ("ACE_ODB::register_object");
+ int i;
+ int slot = 0;
+
+ for (i = 0; i < this->current_size_; i++)
+ {
+ if (this->object_table_[i].this_ == 0)
+ slot = i;
+ else if (this->object_table_[i].this_ == dumper->this_)
+ {
+ slot = i;
+ break;
+ }
+ }
+
+ if (i == this->current_size_)
+ {
+ slot = this->current_size_++;
+ ACE_ASSERT (this->current_size_ < ACE_ODB::MAX_TABLE_SIZE);
+ }
+ this->object_table_[slot].this_ = dumper->this_;
+ this->object_table_[slot].dumper_ = dumper;
+}
+
+void
+ACE_ODB::remove_object (const void *this_ptr)
+{
+ ACE_TRACE ("ACE_ODB::remove_object");
+ int i;
+
+ for (i = 0; i < this->current_size_; i++)
+ {
+ if (this->object_table_[i].this_ == this_ptr)
+ break;
+ }
+
+ if (i < this->current_size_)
+ {
+ this->object_table_[i].this_ = 0;
+ this->object_table_[i].dumper_ = 0;
+ }
+}
+
+ACE_ODB *ACE_ODB::instance_ = 0;
diff --git a/ace/Logging/Dump.h b/ace/Logging/Dump.h
new file mode 100644
index 00000000000..552a49300a8
--- /dev/null
+++ b/ace/Logging/Dump.h
@@ -0,0 +1,168 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Dump.h
+ *
+ * $Id$
+ *
+ *
+ * A prototype mechanism that allow all ACE objects to be registered
+ * with a central in-memory "database" that can dump the state of all
+ * live ACE objects (e.g., from within a debugger).
+ *
+ * The macros which allow easy registration and removal of objects to be
+ * dumped (ACE_REGISTER_OBJECT and ACE_REMOVE_OBJECT) are turned into
+ * no-ops by compiling with the ACE_NDEBUG macro defined. This allows
+ * usage to be removed in "release mode" builds without changing code.
+ *
+ * There are several interesting aspects to this design:
+ *
+ * 1. It uses the External Polymorphism pattern to avoid having to
+ * derive all ACE classes from a common base class that has virtual
+ * methods (this is crucial to avoid unnecessary overhead). In
+ * addition, there is no additional space added to ACE objects
+ * (this is crucial to maintain binary layout compatibility).
+ *
+ * 2. This mechanism can be conditionally compiled in order to
+ * completely disable this feature entirely. Moreover, by
+ * using macros there are relatively few changes to ACE code.
+ *
+ * 3. This mechanism copes with single-inheritance hierarchies of
+ * dumpable classes. In such cases we typically want only one
+ * dump, corresponding to the most derived instance. Thanks to
+ * Christian Millour (chris@etca.fr) for illustrating how to do
+ * this. Note, however, that this scheme doesn't generalize to
+ * work with multiple-inheritance or virtual base classes.
+ *
+ * Future work includes:
+ *
+ * 1. Using a dynamic object table rather than a static table
+ *
+ * 2. Adding support to allow particular classes of objects to
+ * be selectively dumped.
+ *
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_DUMP_H
+#define ACE_DUMP_H
+#include "ace/pre.h"
+
+#include "ace/Synch.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Dumpable
+ *
+ * @brief Base class that defines a uniform interface for all object
+ * dumping.
+ */
+class ACE_Export ACE_Dumpable
+{
+public:
+ friend class ACE_ODB;
+ friend class ACE_Dumpable_Ptr;
+
+ /// Constructor.
+ ACE_Dumpable (const void *);
+
+ /// This pure virtual method must be filled in by a subclass.
+ virtual void dump (void) const = 0;
+
+protected:
+ virtual ~ACE_Dumpable (void);
+
+private:
+ /// Pointer to the object that is being stored.
+ const void *this_;
+};
+
+/**
+ * @class ACE_Dumpable_Ptr
+ *
+ * @brief A smart pointer stored in the in-memory object database
+ * ACE_ODB. The pointee (if any) is deleted when reassigned.
+ */
+class ACE_Export ACE_Dumpable_Ptr
+{
+public:
+ ACE_Dumpable_Ptr (const ACE_Dumpable *dumper = 0);
+ const ACE_Dumpable *operator->() const;
+ void operator= (const ACE_Dumpable *dumper) const;
+
+private:
+ /// "Real" pointer to the underlying abstract base class
+ /// pointer that does the real work.
+ const ACE_Dumpable *dumper_;
+};
+
+/**
+ * @class ACE_ODB
+ *
+ * @brief This is the object database (ODB) that keeps track of all
+ * live ACE objects.
+ */
+class ACE_Export ACE_ODB
+{
+public:
+ /// @todo This is clearly inadequate and should be dynamic...
+ enum {MAX_TABLE_SIZE = 100000};
+
+ /// Iterates through the entire set of registered objects and
+ /// dumps their state.
+ void dump_objects (void);
+
+ /// Add the tuple <dumper, this_> to the list of registered ACE objects.
+ void register_object (const ACE_Dumpable *dumper);
+
+ /// Use <this_> to locate and remove the associated <dumper> from the
+ /// list of registered ACE objects.
+ void remove_object (const void *this_);
+
+ /// Interface to the Singleton instance of the object database.
+ static ACE_ODB *instance (void);
+
+private:
+ ACE_ODB (void); // Ensure we have a Singleton...
+
+ struct Tuple
+ {
+ const void *this_;
+ // Pointer to the object that is registered.
+
+ const ACE_Dumpable_Ptr dumper_;
+ // Smart pointer to the ACE_Dumpable object associated with this_.
+ // This uses an ACE_Dumpable_Ptr, instead of a bare pointer, to
+ // cope with hierarchies of dumpable classes. In such cases we
+ // typically want only one dump, corresponding to the most derived
+ // instance. To achieve this, the handle registered for the
+ // subobject corresponding to the base class is destroyed (hence
+ // on destruction of the subobject its handle won't exist anymore
+ // and we'll have to check for that).
+
+ Tuple (void) : dumper_(0) {}
+ };
+
+ /// Singleton instance of this class.
+ static ACE_ODB *instance_;
+
+ /// The current implementation is very simple-minded and will be
+ /// changed to be dynamic.
+ Tuple object_table_[ACE_ODB::MAX_TABLE_SIZE];
+
+ /// Current size of <object_table_>.
+ int current_size_;
+};
+
+// Include the templates classes at this point.
+#include "ace/Dump_T.h"
+
+#include "ace/post.h"
+#endif /* ACE_DUMP_H */
diff --git a/ace/Logging/Dump_T.cpp b/ace/Logging/Dump_T.cpp
new file mode 100644
index 00000000000..97386d4ba31
--- /dev/null
+++ b/ace/Logging/Dump_T.cpp
@@ -0,0 +1,41 @@
+// Dump_T.cpp
+// $Id$
+
+#ifndef ACE_DUMP_T_C
+#define ACE_DUMP_T_C
+
+#include "ace/Dump_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_RCSID(ace, Dump_T, "$Id$")
+
+template <class Concrete>
+ACE_Dumpable_Adapter<Concrete>::~ACE_Dumpable_Adapter (void)
+{
+ ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::~ACE_Dumpable_Adapter");
+}
+
+template <class Concrete>
+ACE_Dumpable_Adapter<Concrete>::ACE_Dumpable_Adapter (const Concrete *t)
+ : ACE_Dumpable ((const void *) t), this_ (t)
+{
+ ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::ACE_Dumpable_Adapter");
+}
+
+template <class Concrete> Concrete *
+ACE_Dumpable_Adapter<Concrete>::operator->() const
+{
+ return (Concrete *) this->this_;
+}
+
+template <class Concrete> void
+ACE_Dumpable_Adapter<Concrete>::dump (void) const
+{
+ ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::dump");
+ this->this_->dump ();
+}
+
+#endif /* ACE_DUMP_T_C */
diff --git a/ace/Logging/Dump_T.h b/ace/Logging/Dump_T.h
new file mode 100644
index 00000000000..be283889da9
--- /dev/null
+++ b/ace/Logging/Dump_T.h
@@ -0,0 +1,78 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Dump_T.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_DUMP_T_H
+#define ACE_DUMP_T_H
+#include "ace/pre.h"
+
+#include "ace/Dump.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Dumpable_Adapter
+ *
+ * @brief This class inherits the interface of the abstract ACE_Dumpable
+ * class and is instantiated with the implementation of the
+ * concrete component class <class Concrete>.
+ *
+ * This design is similar to the Adapter and Decorator patterns
+ * from the ``Gang of Four'' book. Note that <class Concrete>
+ * need not inherit from a common class since ACE_Dumpable
+ * provides the uniform virtual interface!
+ */
+template <class Concrete>
+class ACE_Dumpable_Adapter : public ACE_Dumpable
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Dumpable_Adapter (const Concrete *t);
+ ~ACE_Dumpable_Adapter (void);
+
+ /// Concrete dump method (simply delegates to the <dump> method of
+ /// <class Concrete>).
+ virtual void dump (void) const;
+
+ /// Delegate to methods in the Concrete class.
+ Concrete *operator->() const;
+
+private:
+ /// Pointer to <this> of <class Concrete>.
+ const Concrete *this_;
+};
+
+// Some useful macros for conditionally compiling this feature...
+#if defined (ACE_NDEBUG)
+#define ACE_REGISTER_OBJECT(CLASS)
+#define ACE_REMOVE_OBJECT
+#else
+#define ACE_REGISTER_OBJECT(CLASS) \
+ ACE_ODB::instance ()->register_object \
+ (new ACE_Dumpable_Adapter<CLASS> (this));
+#define ACE_REMOVE_OBJECT \
+ ACE_ODB::instance ()->remove_object \
+ ((void *) this);
+#endif /* ACE_NDEBUG */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Dump_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Dump_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_DUMP_T_H */
diff --git a/ace/Logging/Log_Msg.cpp b/ace/Logging/Log_Msg.cpp
new file mode 100644
index 00000000000..5c0420a0955
--- /dev/null
+++ b/ace/Logging/Log_Msg.cpp
@@ -0,0 +1,2109 @@
+// $Id$
+
+// We need this to get the status of ACE_NTRACE...
+#include "ace/config-all.h"
+
+// Turn off tracing for the duration of this file.
+#if defined (ACE_NTRACE)
+# undef ACE_NTRACE
+#endif /* ACE_NTRACE */
+#define ACE_NTRACE 1
+
+#include "ace/ACE.h"
+#include "ace/Thread_Manager.h"
+#include "ace/OS.h"
+
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE == 0)
+# include "ace/Object_Manager.h"
+#endif /* ! ACE_MT_SAFE */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Msg_IPC.h"
+#include "ace/Log_Msg_NT_Event_Log.h"
+#include "ace/Log_Msg_UNIX_Syslog.h"
+
+ACE_RCSID(ace, Log_Msg, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Log_Msg)
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ int ACE_Log_Msg::key_created_ = 0;
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ ACE_thread_key_t ACE_Log_Msg::log_msg_tss_key_;
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ACE_MT_SAFE */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_NT_Event_Log
+#elif !defined (ACE_LACKS_UNIX_SYSLOG) && !defined (ACE_HAS_WINCE)
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_UNIX_Syslog
+#else
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_IPC
+#endif /* ! ACE_WIN32 */
+
+// This is only needed here because we can't afford to call
+// ACE_LOG_MSG->instance() from within ACE_Log_Msg::instance() or else
+// we will recurse infinitely! Not for public use!
+#define ACE_NEW_RETURN_I(POINTER,CONSTRUCTOR,RET_VAL) \
+ do { POINTER = new CONSTRUCTOR; \
+ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
+ } while (0)
+
+// Instance count for Log_Msg - used to know when dynamically
+// allocated storage (program name and host name) can be safely
+// deleted.
+int ACE_Log_Msg::instance_count_ = 0;
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+# if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE == 0)
+ template class ACE_Cleanup_Adapter<ACE_Log_Msg>;
+#else
+template class ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex>;
+template class ACE_Guard<ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex> >;
+# endif /* ! ACE_MT_SAFE */
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+# if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE == 0)
+# pragma instantiate ACE_Cleanup_Adapter<ACE_Log_Msg>
+#else
+#pragma instantiate ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex>
+#pragma instantiate ACE_Guard<ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex> >
+# endif /* ! ACE_MT_SAFE */
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+class ACE_Log_Msg_Manager
+ // = TITLE
+ // Synchronize output operations.
+ //
+ // = DESCRIPTION
+ // Provides global point of contact for all ACE_Log_Msg instances
+ // in a process.
+ //
+ // For internal use by ACE, only!
+{
+public:
+ static ACE_Log_Msg_Backend *log_backend_;
+
+ static u_long log_backend_flags_;
+
+ static int init_backend (const u_long *flags = 0);
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ static void close (void);
+
+ static ACE_Recursive_Thread_Mutex *get_lock (void);
+
+private:
+ static ACE_Recursive_Thread_Mutex *lock_;
+#endif /* ! ACE_MT_SAFE */
+};
+
+ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::log_backend_ = 0;
+u_long ACE_Log_Msg_Manager::log_backend_flags_ = 0;
+
+int ACE_Log_Msg_Manager::init_backend (const u_long *flags)
+{
+ // If flags have been supplied, and they are different from the flags
+ // we had last time, then we may have to re-create the backend as a
+ // different type.
+ if (flags)
+ {
+ if ((ACE_BIT_ENABLED (*flags, ACE_Log_Msg::SYSLOG)
+ && ACE_BIT_DISABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
+ || (ACE_BIT_DISABLED (*flags, ACE_Log_Msg::SYSLOG)
+ && ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG)))
+ {
+ delete ACE_Log_Msg_Manager::log_backend_;
+ ACE_Log_Msg_Manager::log_backend_ = 0;
+ }
+
+ ACE_Log_Msg_Manager::log_backend_flags_ = *flags;
+ }
+
+ if (ACE_Log_Msg_Manager::log_backend_ == 0)
+ {
+ ACE_NO_HEAP_CHECK;
+
+#if defined (WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+ // Allocate the ACE_Log_Msg_Backend instance.
+ if (ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
+ ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
+ ACE_LOG_MSG_SYSLOG_BACKEND,
+ -1);
+ else
+#endif /* defined (WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP) */
+ ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
+ ACE_Log_Msg_IPC,
+ -1);
+ }
+
+ return 0;
+}
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ACE_Recursive_Thread_Mutex *ACE_Log_Msg_Manager::lock_ = 0;
+
+ACE_Recursive_Thread_Mutex *
+ACE_Log_Msg_Manager::get_lock (void)
+{
+ // This function is called by the first thread to create an ACE_Log_Msg
+ // instance. It makes the call while holding a mutex, so we don't have
+ // to grab another one here.
+
+ if (ACE_Log_Msg_Manager::lock_ == 0)
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_NEW_RETURN_I (ACE_Log_Msg_Manager::lock_,
+ ACE_Recursive_Thread_Mutex,
+ 0);
+ }
+
+ if (init_backend () == -1)
+ return 0;
+
+ return ACE_Log_Msg_Manager::lock_;
+}
+
+void
+ACE_Log_Msg_Manager::close (void)
+{
+#if defined (ACE_HAS_STHREADS) && ! defined (ACE_HAS_TSS_EMULATION) && ! defined (ACE_HAS_EXCEPTIONS)
+ // Delete the (main thread's) Log_Msg instance. I think that this
+ // is only "necessary" if exception handling is not enabled.
+ // Without exception handling, main thread TSS destructors don't
+ // seem to be called. It's not really necessary anyways, because
+ // this one leak is harmless on Solaris.
+ delete ACE_Log_Msg::instance ();
+#endif /* ACE_HAS_STHREADS && ! TSS_EMULATION && ! ACE_HAS_EXCEPTIONS */
+
+ // Ugly, ugly, but don't know a better way.
+ delete ACE_Log_Msg_Manager::lock_;
+ ACE_Log_Msg_Manager::lock_ = 0;
+
+ delete ACE_Log_Msg_Manager::log_backend_;
+ ACE_Log_Msg_Manager::log_backend_ = 0;
+}
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+/* static */
+# if defined (ACE_HAS_THR_C_DEST)
+# define LOCAL_EXTERN_PREFIX extern "C"
+# else
+# define LOCAL_EXTERN_PREFIX
+# endif /* ACE_HAS_THR_C_DEST */
+LOCAL_EXTERN_PREFIX
+void
+ACE_TSS_cleanup (void *ptr)
+{
+#if !defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
+ // Delegate to thr_desc if this not has terminated
+ ACE_Log_Msg* log_msg = (ACE_Log_Msg*) ptr;
+ if (log_msg->thr_desc()!=0)
+ log_msg->thr_desc()->log_msg_cleanup(log_msg);
+ else
+#endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
+ delete (ACE_Log_Msg *) ptr;
+}
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ! ACE_MT_SAFE */
+
+/* static */
+int
+ACE_Log_Msg::exists (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ ACE_Log_Msg *tss_log_msg = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ return key_created_
+ && ACE_Thread::getspecific (log_msg_tss_key_,
+ ACE_reinterpret_cast (void **,
+ &tss_log_msg)) != -1
+ && tss_log_msg;
+# else
+# error "Platform must support thread-specific storage if threads are used."
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#else /* ! ACE_MT_SAFE */
+ return 1;
+#endif /* ! ACE_MT_SAFE */
+}
+
+ACE_Log_Msg *
+ACE_Log_Msg::instance (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ // TSS Singleton implementation.
+
+ if (key_created_ == 0)
+ {
+ ACE_thread_mutex_t *lock =
+ ACE_reinterpret_cast (ACE_thread_mutex_t *,
+ ACE_OS_Object_Manager::preallocated_object
+ [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
+
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_lock (lock);
+
+ if (key_created_ == 0)
+ {
+ // Allocate the Singleton lock.
+ ACE_Log_Msg_Manager::get_lock ();
+
+ {
+ ACE_NO_HEAP_CHECK;
+ if (ACE_Thread::keycreate (&log_msg_tss_key_,
+ &ACE_TSS_cleanup) != 0)
+ {
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_unlock (lock);
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+
+ key_created_ = 1;
+ }
+
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_unlock (lock);
+ }
+
+ ACE_Log_Msg *tss_log_msg = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ if (ACE_Thread::getspecific (log_msg_tss_key_,
+ ACE_reinterpret_cast (void **,
+ &tss_log_msg)) == -1)
+ return 0; // This should not happen!
+
+ // Check to see if this is the first time in for this thread.
+ if (tss_log_msg == 0)
+ {
+ // Allocate memory off the heap and store it in a pointer in
+ // thread-specific storage (on the stack...). Stop heap
+ // checking, the memory will always be freed by the thread
+ // rundown because of the TSS callback set up when the key was
+ // created. This prevents from getting these blocks reported as
+ // memory leaks.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_NEW_RETURN_I (tss_log_msg,
+ ACE_Log_Msg,
+ 0);
+ // Store the dynamically allocated pointer in thread-specific
+ // storage. It gets deleted via the ACE_TSS_cleanup function
+ // when the thread terminates.
+
+ if (ACE_Thread::setspecific (log_msg_tss_key_,
+ ACE_reinterpret_cast (void *,
+ tss_log_msg)) != 0)
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+
+ return tss_log_msg;
+# else
+# error "Platform must support thread-specific storage if threads are used."
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#else /* ! ACE_MT_SAFE */
+ // We don't have threads, we cannot call
+ // ACE_Log_Msg_Manager::get_lock () to initialize the logger
+ // callback, so instead we do it here.
+ if (ACE_Log_Msg_Manager::init_backend () == -1)
+ return 0;
+
+ // Singleton implementation.
+ static ACE_Cleanup_Adapter<ACE_Log_Msg> *log_msg = 0;
+ if (log_msg == 0)
+ {
+ ACE_NEW_RETURN (log_msg, ACE_Cleanup_Adapter<ACE_Log_Msg>, 0);
+ // Register the instance for destruction at program termination.
+ ACE_Object_Manager::at_exit (log_msg);
+ }
+
+ return &log_msg->object ();
+#endif /* ! ACE_MT_SAFE */
+}
+
+// Sets the flag in the default priority mask used to initialize
+// ACE_Log_Msg instances, as well as the current per-thread instance.
+
+void
+ACE_Log_Msg::enable_debug_messages (ACE_Log_Priority priority)
+{
+ ACE_SET_BITS (ACE_Log_Msg::default_priority_mask_, priority);
+ ACE_Log_Msg *i = ACE_Log_Msg::instance ();
+ i->priority_mask (i->priority_mask () | priority);
+}
+
+// Clears the flag in the default priority mask used to initialize
+// ACE_Log_Msg instances, as well as the current per-thread instance.
+
+void
+ACE_Log_Msg::disable_debug_messages (ACE_Log_Priority priority)
+{
+ ACE_CLR_BITS (ACE_Log_Msg::default_priority_mask_, priority);
+ ACE_Log_Msg *i = ACE_Log_Msg::instance ();
+ i->priority_mask (i->priority_mask () & ~priority);
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::program_name (void)
+{
+ return ACE_Log_Msg::program_name_;
+}
+
+// Name of the local host.
+const ACE_TCHAR *ACE_Log_Msg::local_host_ = 0;
+
+// Records the program name.
+const ACE_TCHAR *ACE_Log_Msg::program_name_ = 0;
+
+// Default is to use stderr.
+u_long ACE_Log_Msg::flags_ = ACE_Log_Msg::STDERR;
+
+// Process id of the current process.
+pid_t ACE_Log_Msg::pid_ = -1;
+
+// Current offset of msg_[].
+int ACE_Log_Msg::msg_off_ = 0;
+
+// Default per-thread priority mask
+// By default, no priorities are enabled.
+u_long ACE_Log_Msg::default_priority_mask_ = 0;
+
+// Default per-process priority mask
+// By default, all priorities are enabled.
+u_long ACE_Log_Msg::process_priority_mask_ = LM_SHUTDOWN
+ | LM_TRACE
+ | LM_DEBUG
+ | LM_INFO
+ | LM_NOTICE
+ | LM_WARNING
+ | LM_STARTUP
+ | LM_ERROR
+ | LM_CRITICAL
+ | LM_ALERT
+ | LM_EMERGENCY;
+
+void
+ACE_Log_Msg::close (void)
+{
+ // This call needs to go here to avoid memory leaks.
+ ACE_MT (ACE_Log_Msg_Manager::close ());
+
+ // Please note that this will be called by a statement that is
+ // harded coded into the ACE_Object_Manager's shutdown sequence, in
+ // its destructor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && \
+ (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION))
+
+ if (key_created_ == 1)
+ {
+ ACE_thread_mutex_t *lock =
+ ACE_reinterpret_cast (ACE_thread_mutex_t *,
+ ACE_OS_Object_Manager::preallocated_object
+ [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
+ ACE_OS::thread_mutex_lock (lock);
+
+ if (key_created_ == 1)
+ {
+ // The same as the ACE_TSS_Cleanup's own key doesn't get
+ // detached, the log_msg_tss_key_ won't get detached
+ // until ACE_TSS_Cleanup::free_all_keys_left, so it will
+ // be in the ACE_TSS_Cleanup::table_. However, there's
+ // no resource associated with it, so we don't need to
+ // keyfree it. The dynamic memory associated with it was
+ // already deleted by ACE_TSS_Cleanup::exit (), so we
+ // don't want to access it again.
+ key_created_ = 0;
+ }
+
+ ACE_OS::thread_mutex_unlock (lock);
+ }
+#endif /* (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) && ACE_MT_SAFE */
+}
+
+void
+ACE_Log_Msg::sync_hook (const ACE_TCHAR *prg_name)
+{
+ ACE_LOG_MSG->sync (prg_name);
+}
+
+ACE_OS_Thread_Descriptor *
+ACE_Log_Msg::thr_desc_hook (void)
+{
+ return ACE_LOG_MSG->thr_desc ();
+}
+
+// Call after a fork to resynchronize the PID and PROGRAM_NAME
+// variables.
+void
+ACE_Log_Msg::sync (const ACE_TCHAR *prog_name)
+{
+ ACE_TRACE ("ACE_Log_Msg::sync");
+
+ if (prog_name)
+ {
+ // Must free if already allocated!!!
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+
+ // Stop heap checking, block will be freed by the destructor when
+ // the last ACE_Log_Msg instance is deleted.
+ // Heap checking state will be restored when the block is left.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_Log_Msg::program_name_ = ACE_OS::strdup (prog_name);
+ }
+ }
+
+ ACE_Log_Msg::pid_ = ACE_OS::getpid ();
+ ACE_Log_Msg::msg_off_ = 0;
+}
+
+u_long
+ACE_Log_Msg::flags (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::flags");
+ u_long result;
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ result = ACE_Log_Msg::flags_;
+ return result;
+}
+
+void
+ACE_Log_Msg::set_flags (u_long flgs)
+{
+ ACE_TRACE ("ACE_Log_Msg::set_flags");
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+
+ ACE_SET_BITS (ACE_Log_Msg::flags_, flgs);
+}
+
+void
+ACE_Log_Msg::clr_flags (u_long flgs)
+{
+ ACE_TRACE ("ACE_Log_Msg::clr_flags");
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, flgs);
+}
+
+int
+ACE_Log_Msg::acquire (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::acquire");
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ return ACE_Log_Msg_Manager::get_lock ()->acquire ();
+#else /* ! ACE_MT_SAFE */
+ return 0;
+#endif /* ! ACE_MT_SAFE */
+}
+
+u_long
+ACE_Log_Msg::priority_mask (u_long n_mask, MASK_TYPE mask_type)
+{
+ u_long o_mask;
+
+ if (mask_type == THREAD) {
+ o_mask = this->priority_mask_;
+ this->priority_mask_ = n_mask;
+ }
+ else {
+ o_mask = ACE_Log_Msg::process_priority_mask_;
+ ACE_Log_Msg::process_priority_mask_ = n_mask;
+ }
+
+ return o_mask;
+}
+
+u_long
+ACE_Log_Msg::priority_mask (MASK_TYPE mask_type)
+{
+ return mask_type == THREAD ? this->priority_mask_
+ : ACE_Log_Msg::process_priority_mask_;
+}
+
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority)
+{
+ return ACE_BIT_ENABLED (this->priority_mask_ |
+ ACE_Log_Msg::process_priority_mask_,
+ log_priority);
+}
+
+int
+ACE_Log_Msg::release (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::release");
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ return ACE_Log_Msg_Manager::get_lock ()->release ();
+#else /* ! ACE_MT_SAFE */
+ return 0;
+#endif /* ! ACE_MT_SAFE */
+}
+
+ACE_Log_Msg::ACE_Log_Msg (void)
+ : status_ (0),
+ errnum_ (0),
+ linenum_ (0),
+ restart_ (1), // Restart by default...
+ ostream_ (0),
+ msg_callback_ (0),
+ trace_depth_ (0),
+ trace_active_ (0),
+ tracing_enabled_ (1), // On by default?
+ delete_ostream_(0),
+ thr_desc_ (0),
+ priority_mask_ (default_priority_mask_)
+{
+ // ACE_TRACE ("ACE_Log_Msg::ACE_Log_Msg");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+ ++instance_count_;
+
+ if (this->instance_count_ == 1)
+ ACE_Base_Thread_Adapter::set_log_msg_hooks (ACE_Log_Msg::init_hook,
+ ACE_Log_Msg::inherit_hook,
+ ACE_Log_Msg::close,
+ ACE_Log_Msg::sync_hook,
+ ACE_Log_Msg::thr_desc_hook);
+
+ this->conditional_values_.is_set_ = 0;
+}
+
+ACE_Log_Msg::~ACE_Log_Msg (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ int instance_count;
+
+ // Only hold the guard while updating the instance_count_.
+ // If ACE_Log_Msg_Manager::close () is called, the lock will
+ // be deleted.
+ {
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+ instance_count = --instance_count_;
+ }
+ // Release the guard.
+
+#else /* ! ACE_MT_SAFE */
+ int instance_count = --instance_count_;
+#endif /* ! ACE_MT_SAFE */
+
+ // If this is the last instance then cleanup. Only the last
+ // thread to destroy its ACE_Log_Msg instance should execute
+ // this block.
+ if (instance_count == 0)
+ {
+ // Destroy the message queue instance.
+ if (ACE_Log_Msg_Manager::log_backend_ != 0)
+ ACE_Log_Msg_Manager::log_backend_->close ();
+
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_TSS_EMULATION)
+ ACE_Log_Msg_Manager::close ();
+# endif /* ACE_HAS_TSS_EMULATION */
+# endif /* ACE_MT_SAFE */
+
+ if (ACE_Log_Msg::program_name_)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+ ACE_Log_Msg::program_name_ = 0;
+ }
+
+ if (ACE_Log_Msg::local_host_)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
+ ACE_Log_Msg::local_host_ = 0;
+ }
+ }
+
+ //
+ // do we need to close and clean up?
+ //
+ if (this->delete_ostream_ == 1)
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ {
+ ACE_OS::fclose (this->ostream_);
+ }
+#else
+ {
+ delete ostream_;
+ }
+#endif
+}
+
+// Open the sender-side of the message queue.
+
+int
+ACE_Log_Msg::open (const ACE_TCHAR *prog_name,
+ u_long flags,
+ const ACE_TCHAR *logger_key)
+{
+ ACE_TRACE ("ACE_Log_Msg::open");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), -1));
+
+ if (prog_name)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+
+ // Stop heap checking, block will be freed by the destructor.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
+ ACE_OS::strdup (prog_name),
+ -1);
+ }
+ }
+ else if (ACE_Log_Msg::program_name_ == 0)
+ {
+ // Stop heap checking, block will be freed by the destructor.
+ ACE_NO_HEAP_CHECK;
+ ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
+ ACE_OS::strdup (ACE_LIB_TEXT ("<unknown>")),
+ -1);
+ }
+
+ int status = 0;
+
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend (&flags));
+
+ // Always close the current handle before doing anything else.
+ ACE_Log_Msg_Manager::log_backend_->reset ();
+
+ // Note that if we fail to open the message queue the default action
+ // is to use stderr (set via static initialization in the
+ // Log_Msg.cpp file).
+
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER)
+ || ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
+ {
+ // The SYSLOG backends (both NT and UNIX) can get along fine
+ // without the logger_key.
+ if (logger_key == 0 && ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
+ status = -1;
+ else
+ {
+ status =
+ ACE_Log_Msg_Manager::log_backend_->open (logger_key);
+ }
+
+ if (status == -1)
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
+ else
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ }
+ else if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER))
+ {
+ // If we are closing down logger, redirect logging to stderr.
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
+ }
+
+ // Remember, ACE_Log_Msg::STDERR bit is on by default...
+ if (status != -1
+ && ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::STDERR) == 0)
+ ACE_CLR_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::STDERR);
+
+ // VERBOSE takes precedence over VERBOSE_LITE...
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::VERBOSE_LITE))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::VERBOSE_LITE);
+ else if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::VERBOSE))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::VERBOSE);
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::OSTREAM))
+ {
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::OSTREAM);
+ // Only set this to cerr if it hasn't already been set.
+ if (this->msg_ostream () == 0)
+ this->msg_ostream (ACE_DEFAULT_LOG_STREAM);
+ }
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::MSG_CALLBACK))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::MSG_CALLBACK);
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::SILENT))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT);
+
+ return status;
+}
+
+// Valid Options (prefixed by '%', as in printf format strings) include:
+// 'A': print an ACE_timer_t value
+// 'a': exit the program at this point (var-argument is the exit status!)
+// 'c': print a character
+// 'C': print a character string
+// 'i', 'd': print a decimal number
+// 'I', indent according to nesting depth
+// 'e', 'E', 'f', 'F', 'g', 'G': print a double
+// 'l', print line number where an error occurred.
+// 'M': print the name of the priority of the message.
+// 'm': Return the message corresponding to errno value, e.g., as done by <strerror>
+// 'N': print file name where the error occurred.
+// 'n': print the name of the program (or "<unknown>" if not set)
+// 'o': print as an octal number
+// 'P': format the current process id
+// 'p': format the appropriate errno message from sys_errlist, e.g., as done by <perror>
+// 'Q': print out the uint64 number
+// 'r': call the function pointed to by the corresponding argument
+// 'R': print return status
+// 'S': format the appropriate _sys_siglist entry corresponding to var-argument.
+// 's': format a character string
+// 'T': print timestamp in hour:minute:sec:usec format.
+// 'D': print timestamp in month/day/year hour:minute:sec:usec format.
+// 't': print thread id (1 if single-threaded)
+// 'u': print as unsigned int
+// 'X', 'x': print as a hex number
+// 'w': print a wide character
+// 'W': print out a wide character string.
+// '%': format a single percent sign, '%'
+
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Priority log_priority,
+ const ACE_TCHAR *format_str, ...)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+
+ // Start of variable args section.
+ va_list argp;
+
+ va_start (argp, format_str);
+
+ int result = this->log (format_str,
+ log_priority,
+ argp);
+ va_end (argp);
+
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+/**
+ * Since this is the ANTI_TCHAR version, we need to convert
+ * the format string over.
+ */
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Priority log_priority,
+ const ACE_ANTI_TCHAR *format_str, ...)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+
+ // Start of variable args section.
+ va_list argp;
+
+ va_start (argp, format_str);
+
+ int result = this->log (ACE_TEXT_ANTI_TO_TCHAR (format_str),
+ log_priority,
+ argp);
+ va_end (argp);
+
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ssize_t
+ACE_Log_Msg::log (const ACE_TCHAR *format_str,
+ ACE_Log_Priority log_priority,
+ va_list argp)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+ // External decls.
+
+#if ! (defined(__BORLANDC__) && __BORLANDC__ >= 0x0530) \
+ && !defined(__MINGW32__)
+#if defined (__FreeBSD__) || defined(__QNX__)
+ extern const int sys_nerr;
+#elif defined (__CYGWIN32__)
+# define sys_nerr _sys_nerr
+#else
+ extern int sys_nerr;
+#endif /* !__FreeBSD__ && !__QNX__ */
+#endif /* ! (defined(__BORLANDC__) && __BORLANDC__ >= 0x0530) */
+ typedef void (*PTF)(...);
+
+ // Check if there were any conditional values set.
+ int conditional_values = this->conditional_values_.is_set_;
+
+ // Reset conditional values.
+ this->conditional_values_.is_set_ = 0;
+
+ // Only print the message if <priority_mask_> hasn't been reset to
+ // exclude this logging priority.
+ if (this->log_priority_enabled (log_priority) == 0)
+ return 0;
+
+ // If conditional values were set and the log priority is correct,
+ // then the values are actually set.
+ if (conditional_values)
+ this->set (this->conditional_values_.file_,
+ this->conditional_values_.line_,
+ this->conditional_values_.op_status_,
+ this->conditional_values_.errnum_,
+ this->restart (),
+ this->msg_ostream (),
+ this->msg_callback ());
+
+ // Logging is a benign activity, so don't inadvertently smash errno.
+ ACE_Errno_Guard guard (errno);
+
+ ACE_Log_Record log_record (log_priority,
+ ACE_OS::gettimeofday (),
+ this->getpid ());
+ ACE_TCHAR *bp = ACE_const_cast (ACE_TCHAR *, this->msg ());
+ int abort_prog = 0;
+ int exit_value = 0;
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE))
+ {
+ // Prepend the program name onto this message
+
+ if (ACE_Log_Msg::program_name_ != 0)
+ {
+ for (const ACE_TCHAR *s = ACE_Log_Msg::program_name_;
+ (*bp = *s) != '\0';
+ s++)
+ bp++;
+
+ *bp++ = '|';
+ }
+ }
+
+ while (*format_str != '\0')
+ {
+ // Copy input to output until we encounter a %, however a
+ // % followed by another % is not a format specification.
+
+ if (*format_str != '%')
+ *bp++ = *format_str++;
+ else if (format_str[1] == '%') // An "escaped" '%' (just print one '%').
+ {
+ *bp++ = *format_str++; // Store first %
+ format_str++; // but skip second %
+ }
+ else
+ {
+ // This is most likely a format specification that ends with
+ // one of the valid options described previously. To enable full
+ // use of all sprintf capabilities, save the format specifier
+ // from the '%' up to the format letter in a new char array.
+ // This allows the full sprintf capability for padding, field
+ // widths, alignment, etc. Any width/precision requiring a
+ // caller-supplied argument is extracted and placed as text
+ // into the format array. Lastly, we convert the caller-supplied
+ // format specifier from the ACE_Log_Msg-supported list to the
+ // equivalent sprintf specifier, and run the new format spec
+ // through sprintf, adding it to the bp string.
+
+ const ACE_TCHAR *start_format = format_str;
+ ACE_TCHAR format[128]; // Converted format string
+ ACE_TCHAR *fp; // Current format pointer
+ int wp = 0; // Width/precision extracted from args
+ int done = 0;
+ int skip_nul_locate = 0;
+
+ fp = format;
+ *fp++ = *format_str++; // Copy in the %
+
+ // Work through the format string to copy in the format
+ // from the caller. While it's going across, extract ints
+ // for '*' width/precision values from the argument list.
+ // When the real format specifier is located, change it to
+ // one recognized by sprintf, if needed, and do the sprintf
+ // call.
+
+ while (!done)
+ {
+ done = 1; // Unless a conversion spec changes it
+
+ switch (*format_str)
+ {
+ // The initial set of cases are the conversion
+ // specifiers. Copy them in to the format array.
+ // Note we don't use 'l', a normal conversion spec,
+ // as a conversion because it is a ACE_Log_Msg format
+ // specifier.
+ case '-':
+ case '+':
+ case '0':
+ case ' ':
+ case '#':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case 'L':
+ case 'h':
+ *fp++ = *format_str;
+ done = 0;
+ break;
+
+ case '*':
+ wp = va_arg (argp, int);
+ ACE_OS::sprintf (fp, ACE_LIB_TEXT ("%d"), wp);
+ fp += ACE_OS::strlen (fp);
+ done = 0;
+ break;
+
+ case 'A': // ACE_timer_t
+ {
+#if defined (ACE_LACKS_FLOATING_POINT)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ld"));
+ ACE_UINT32 value = va_arg (argp, ACE_UINT32);
+ ACE_OS::sprintf (bp, format, value);
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("f"));
+ double value = va_arg (argp, double);
+ ACE_OS::sprintf (bp, format, value);
+#endif /* ACE_LACKS_FLOATING_POINT */
+ }
+ break;
+
+ case 'a': // Abort program after handling all of format string.
+ abort_prog = 1;
+ exit_value = va_arg (argp, int);
+ ACE_OS::strcpy (bp, ACE_LIB_TEXT ("Aborting..."));
+ // Make sure to NULL terminate this...
+ break;
+
+ case 'l': // Source file line number
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ ACE_OS::sprintf (bp, format, this->linenum ());
+ break;
+
+ case 'N': // Source file name
+ // @@ UNICODE
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format,
+ this->file () ?
+ ACE_TEXT_CHAR_TO_TCHAR (this->file ())
+ : ACE_LIB_TEXT ("<unknown file>"));
+ break;
+
+ case 'n': // Program name
+ // @@ UNICODE
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format,
+ ACE_Log_Msg::program_name_ ?
+ ACE_Log_Msg::program_name_ :
+ ACE_LIB_TEXT ("<unknown>"));
+ break;
+
+ case 'P': // Process ID
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ ACE_OS::sprintf (bp, format,
+ ACE_static_cast (int, this->getpid ()));
+ break;
+
+ case 'p': // <errno> string, ala perror()
+ {
+ errno = ACE::map_errno (this->errnum ());
+ if (errno >= 0 && errno < sys_nerr)
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+ ACE_OS::sprintf (bp, format,
+ va_arg (argp, ACE_TCHAR *),
+ ACE_TEXT_CHAR_TO_TCHAR (ACE_OS_String::strerror (errno)));
+ }
+ else
+ {
+#if defined (ACE_WIN32)
+ ACE_TCHAR *lpMsgBuf = 0;
+
+ // PharLap can't do FormatMessage, so try for socket
+ // error.
+# if !defined (ACE_HAS_PHARLAP)
+ ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_MAX_WIDTH_MASK
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ NULL);
+# endif /* ACE_HAS_PHARLAP */
+
+ // If we don't get a valid response from
+ // <FormatMessage>, we'll assume this is a
+ // WinSock error and so we'll try to convert
+ // it into a string. If this doesn't work it
+ // returns "unknown error" which is fine for
+ // our purposes.
+ if (lpMsgBuf == 0)
+ {
+ const ACE_TCHAR *message =
+ ACE::sock_error (errno);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+ ACE_OS::sprintf (bp, format,
+ va_arg (argp, const ACE_TCHAR *),
+ message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+ ACE_OS::sprintf (bp, format,
+ va_arg (argp, ACE_TCHAR *),
+ lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+#elif !defined (ACE_HAS_WINCE)
+ ACE_OS::strcpy (fp,
+ ACE_LIB_TEXT (
+ "s: <unknown error> = %d"));
+ ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_TCHAR *), errno);
+#endif /* ACE_WIN32 */
+ }
+ break;
+ }
+
+ case 'M': // Print the name of the priority of the message.
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, ACE_Log_Record::priority_name (log_priority));
+ break;
+
+ case 'm': // Format the string assocated with the errno value.
+ {
+ errno = ACE::map_errno (this->errnum ());
+ if (errno >= 0 && errno < sys_nerr)
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp,
+ format,
+ ACE_OS_String::strerror (errno));
+ }
+ else
+ {
+#if defined (ACE_WIN32)
+ ACE_TCHAR *lpMsgBuf = 0;
+
+ // PharLap can't do FormatMessage, so try for socket
+ // error.
+# if !defined (ACE_HAS_PHARLAP)
+ ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_MAX_WIDTH_MASK
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ NULL);
+# endif /* ACE_HAS_PHARLAP */
+
+ // If we don't get a valid response from
+ // <FormatMessage>, we'll assume this is a
+ // WinSock error and so we'll try to convert
+ // it into a string. If this doesn't work it
+ // returns "unknown error" which is fine for
+ // our purposes.
+ if (lpMsgBuf == 0)
+ {
+ const ACE_TCHAR *message =
+ ACE::sock_error (errno);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+#elif !defined (ACE_HAS_WINCE)
+ // Ignore the built format... if this is a problem,
+ // this part can be changed to build another string
+ // and pass that with the complete conversion specs.
+ ACE_OS::sprintf (bp,
+ ACE_LIB_TEXT ("<unknown error> = %d"),
+ errno);
+#endif /* ACE_WIN32 */
+ }
+ break;
+ }
+
+ case 'R': // Format the return status of the operation.
+ this->op_status (va_arg (argp, int));
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ ACE_OS::sprintf (bp, format, this->op_status ());
+ break;
+
+ case '{': // Increment the trace_depth, then indent
+ skip_nul_locate = 1;
+ (void) this->inc ();
+ break;
+
+ case '}': // indent, then decrement trace_depth
+ skip_nul_locate = 1;
+ (void) this->dec ();
+ break;
+
+ case '$': // insert a newline, then indent the next line
+ // according to %I
+ *bp++ = '\n';
+ /* fallthrough */
+
+ case 'I': // Indent with nesting_depth*width spaces
+ // Caller can do %*I to override nesting indent, and
+ // if %*I was done, wp has the extracted width.
+ if (0 == wp)
+ wp = ACE_Trace::get_nesting_indent ();
+ wp *= this->trace_depth_;
+ ACE_OS::memset (bp, ' ', wp);
+ bp += wp;
+ *bp = '\0';
+ skip_nul_locate = 1;
+ break;
+
+ case 'r': // Run (invoke) this subroutine.
+ {
+ int osave = ACE_Log_Msg::msg_off_;
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT))
+ *bp++ = '{';
+ ACE_Log_Msg::msg_off_ = bp - this->msg_;
+
+ (*va_arg (argp, PTF))();
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT))
+ {
+ bp += ACE_OS::strlen (bp);
+ *bp++ = '}';
+ }
+ *bp = '\0';
+ skip_nul_locate = 1;
+ ACE_Log_Msg::msg_off_ = osave;
+ break;
+ }
+
+ case 'S': // format the string for with this signal number.
+ {
+ int sig = va_arg (argp, int);
+#if defined (ACE_HAS_SYS_SIGLIST)
+ if (sig >= 0 && sig < ACE_NSIG)
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, _sys_siglist[sig]);
+ }
+ else
+ ACE_OS::sprintf (bp, ACE_LIB_TEXT ("<unknown signal> %d"),
+ sig);
+#else
+ ACE_OS::sprintf (bp, ACE_LIB_TEXT ("signal %d"), sig);
+#endif /* ACE_HAS_SYS_SIGLIST */
+ break;
+ }
+
+ case 'D': // Format the timestamp in month/day/year
+ // hour:minute:sec:usec format.
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE::timestamp (day_and_time,
+ sizeof day_and_time);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, day_and_time);
+ break;
+ }
+
+ case 'T': // Format the timestamp in
+ // hour:minute:sec:usec format.
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp,
+ format,
+ ACE::timestamp (day_and_time,
+ sizeof day_and_time));
+ break;
+ }
+
+ case 't': // Format thread id.
+#if defined (ACE_WIN32)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ ACE_OS::sprintf (bp,
+ format,
+ ACE_static_cast(unsigned,
+ ACE_Thread::self ()));
+#elif defined (AIX) && (ACE_AIX_MINOR_VERS <= 2)
+ // AIX's pthread_t (ACE_hthread_t) is a pointer, and it's
+ // a little ugly to send that through a %u format. So,
+ // get the kernel thread ID (tid_t) via thread_self() and
+ // display that instead.
+ // This isn't conditionalized on ACE_HAS_THREAD_SELF because
+ // 1. AIX 4.2 doesn't have that def anymore (it messes up
+ // other things)
+ // 2. OSF/1 V3.2 has that def, and I'm not sure what affect
+ // this would have on that.
+ // -Steve Huston, 19-Aug-97
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ ACE_OS::sprintf (bp, format, thread_self());
+#elif defined (DIGITAL_UNIX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ ACE_OS::sprintf (bp, format,
+# if defined (ACE_HAS_THREADS)
+ pthread_getselfseq_np ()
+# else
+ ACE_Thread::self ()
+# endif /* ACE_HAS_THREADS */
+ );
+#else
+ ACE_hthread_t t_id;
+ ACE_Thread::self (t_id);
+
+# if defined (ACE_HAS_PTHREADS_DRAFT4) && defined (HPUX_10)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ // HP-UX 10.x DCE's thread ID is a pointer. Grab the
+ // more meaningful, readable, thread ID. This will match
+ // the one seen in the debugger as well.
+ ACE_OS::sprintf (bp, format,
+ pthread_getunique_np(&t_id));
+# elif defined (ACE_MVS)
+ // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
+ // code for it.
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ ACE_OS::sprintf (bp, format, t_id);
+# else
+ // Yes, this is an ugly C-style cast, but the correct
+ // C++ cast is different depending on whether the t_id
+ // is an integral type or a pointer type. FreeBSD uses
+ // a pointer type, but doesn't have a _np function to
+ // get an integral type, like the OSes above.
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lu"));
+ ACE_OS::sprintf (bp, format, (unsigned long)t_id);
+# endif /* ACE_HAS_PTHREADS_DRAFT4 && HPUX_10 */
+
+#endif /* ACE_WIN32 */
+ break;
+
+ case 's': // String
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+ ACE_OS::sprintf (bp, format, va_arg (argp, wchar_t *));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ ACE_OS::sprintf (bp, format, va_arg (argp, ACE_TCHAR *));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ break;
+
+ case 'C': // Char string, Unicode for Win32/WCHAR
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::sprintf (bp, format, va_arg (argp, ACE_TCHAR *));
+ break;
+
+ case 'W':
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# endif /* ACE_USES_WCHAR */
+ ACE_OS::sprintf (bp, format, va_arg (argp, ACE_TCHAR *));
+#elif defined (ACE_HAS_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+# endif /* HPUX */
+ ACE_OS::sprintf (bp, format, va_arg (argp, wchar_t *));
+#endif /* ACE_WIN32 / ACE_HAS_WCHAR */
+ break;
+
+ case 'w': // Wide character
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("c"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# endif /* ACE_USES_WCHAR */
+ ACE_OS::sprintf (bp, format, va_arg (argp, int));
+#elif defined (ACE_USES_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lc"));
+# endif /* HPUX */
+ ACE_OS::sprintf (bp, format, va_arg (argp, wint_t));
+#else /* ACE_WIN32 */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ ACE_OS::sprintf (bp, format, va_arg (argp, int));
+#endif /* ACE_WIN32 */
+ break;
+
+ case 'c':
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("c"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::sprintf (bp, format, va_arg (argp, int));
+ break;
+
+ case 'd': case 'i': case 'o':
+ case 'u': case 'x': case 'X':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ ACE_OS::sprintf (bp, format, va_arg (argp, int));
+ break;
+
+ case 'F': case 'f': case 'e': case 'E':
+ case 'g': case 'G':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ ACE_OS::sprintf (bp, format, va_arg (argp, double));
+ break;
+
+ case 'Q':
+#if defined (ACE_LACKS_LONGLONG_T)
+ {
+ // This relies on the ACE_U_LongLong storage layout.
+ ACE_UINT32 hi = va_arg (argp, ACE_UINT32);
+ ACE_UINT32 lo = va_arg (argp, ACE_UINT32);
+ if (hi > 0)
+ ACE_OS::sprintf (bp, "0x%lx%0*lx", hi, 2 * sizeof lo,
+ lo);
+ else
+ ACE_OS::sprintf (bp, "0x%lx", lo);
+ }
+#else /* ! ACE_LACKS_LONGLONG_T */
+ {
+ const ACE_TCHAR *fmt = ACE_UINT64_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_UINT64));
+ }
+#endif /* ! ACE_LACKS_LONGLONG_T */
+ break;
+
+ default:
+ // So, it's not a legit format specifier after all...
+ // Copy from the original % to where we are now, then
+ // continue with whatever comes next.
+ while (start_format != format_str)
+ *bp++ = *start_format++;
+ *bp++ = *format_str;
+ break;
+ }
+
+ // Bump to the next char in the caller's format_str
+ format_str++;
+ }
+
+ if (!skip_nul_locate)
+ while (*bp != '\0') // Locate end of bp.
+ bp++;
+ }
+ }
+
+ *bp = '\0'; // Terminate bp, but don't auto-increment this!
+
+ // Check that memory was not corrupted.
+ if (bp >= this->msg_ + sizeof this->msg_)
+ {
+ abort_prog = 1;
+ ACE_OS::fprintf (stderr,
+ "The following logged message is too long!\n");
+ }
+
+ // Copy the message from thread-specific storage into the transfer
+ // buffer (this can be optimized away by changing other code...).
+ log_record.msg_data (this->msg ());
+
+ // Write the <log_record> to the appropriate location.
+ ssize_t result = this->log (log_record,
+ abort_prog);
+
+ if (abort_prog)
+ {
+ // Since we are now calling abort instead of exit, this value is
+ // not used.
+ ACE_UNUSED_ARG (exit_value);
+
+ // *Always* print a message to stderr if we're aborting. We
+ // don't use verbose, however, to avoid recursive aborts if
+ // something is hosed.
+ log_record.print (ACE_Log_Msg::local_host_, 0);
+#if defined (ACE_HAS_WINCE)
+ // @@ WINCE: Is this what we want to do?
+ while (1) ;
+#else
+ ACE_OS::abort ();
+#endif /* ACE_HAS_WINCE */
+ }
+
+ return result;
+}
+
+#if !defined (ACE_WIN32)
+class ACE_Log_Msg_Sig_Guard
+{
+ // = TITLE
+ // Bare-bones ACE_Sig_Guard.
+ //
+ // = DESCRIPTION
+ // For use only by ACE_Log_Msg.
+ // doesn't require the use of global variables or global
+ // functions in an application).
+private:
+ ACE_Log_Msg_Sig_Guard (void);
+ ~ACE_Log_Msg_Sig_Guard (void);
+
+ sigset_t omask_;
+ // Original signal mask.
+
+ friend ssize_t ACE_Log_Msg::log (ACE_Log_Record &log_record,
+ int suppress_stderr);
+};
+
+ACE_Log_Msg_Sig_Guard::ACE_Log_Msg_Sig_Guard (void)
+{
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_OS::sigemptyset (&this->omask_);
+
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ &this->omask_);
+# else
+ ACE_OS::thr_sigsetmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ &this->omask_);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+}
+
+ACE_Log_Msg_Sig_Guard::~ACE_Log_Msg_Sig_Guard (void)
+{
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_SETMASK,
+ &this->omask_,
+ 0);
+# else
+ ACE_OS::thr_sigsetmask (SIG_SETMASK,
+ &this->omask_,
+ 0);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* ! ACE_LACKS_UNIX_SIGNALS */
+}
+#endif /* ! ACE_WIN32 */
+
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Record &log_record,
+ int suppress_stderr)
+{
+ ssize_t result = 0;
+
+ // Format the message and print it to stderr and/or ship it off to
+ // the log_client daemon, and/or print it to the ostream. Of
+ // course, only print the message if "SILENT" mode is disabled.
+ if (ACE_BIT_DISABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT))
+ {
+ int tracing = this->tracing_enabled ();
+ this->stop_tracing ();
+
+#if !defined (ACE_WIN32)
+ // Make this block signal-safe.
+ ACE_Log_Msg_Sig_Guard sb;
+#endif /* !ACE_WIN32 && !ACE_PSOS */
+
+ // Make sure that the lock is held during all this.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (),
+ -1));
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::STDERR)
+ && !suppress_stderr) // This is taken care of by our caller.
+ log_record.print (ACE_Log_Msg::local_host_,
+ ACE_Log_Msg::flags_
+#if defined (ACE_HAS_WINCE)
+ );
+#else
+ , stderr);
+#endif /* ACE_HAS_WINCE */
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::LOGGER))
+ {
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend ());
+
+ result =
+ ACE_Log_Msg_Manager::log_backend_->log (log_record);
+ }
+
+ // This must come last, after the other two print operations
+ // (see the <ACE_Log_Record::print> method for details).
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::OSTREAM)
+ && this->msg_ostream () != 0)
+ log_record.print (ACE_Log_Msg::local_host_,
+ ACE_Log_Msg::flags_,
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ACE_static_cast (FILE *,
+ this->msg_ostream ())
+#else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ *this->msg_ostream ()
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ );
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::MSG_CALLBACK)
+ && this->msg_callback () != 0)
+ {
+ // Use a "reverse lock" to avoid holding the lock during the
+ // callback so we don't have deadlock if the callback uses
+ // the logger.
+ ACE_MT (ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex> reverse_lock
+ (*ACE_Log_Msg_Manager::get_lock ()));
+ ACE_MT (ACE_GUARD_RETURN (ACE_Reverse_Lock<ACE_Recursive_Thread_Mutex>,
+ ace_mon_1, reverse_lock, -1));
+ this->msg_callback ()->log (log_record);
+ }
+ if (tracing)
+ this->start_tracing ();
+ }
+
+ return result;
+}
+
+// Calls log to do the actual print, but formats first.
+
+int
+ACE_Log_Msg::log_hexdump (ACE_Log_Priority log_priority,
+ const char *buffer,
+ int size,
+ const ACE_TCHAR *text)
+{
+ ACE_TCHAR buf[ACE_Log_Record::MAXLOGMSGLEN -
+ ACE_Log_Record::VERBOSE_LEN - 58];
+ // 58 for the HEXDUMP header;
+
+ ACE_TCHAR *msg_buf;
+ size_t text_sz = text ? ACE_OS::strlen(text) : 0;
+ ACE_NEW_RETURN (msg_buf,
+ ACE_TCHAR[text_sz + 58],
+ -1);
+
+ buf[0] = 0; // in case size = 0
+
+ int len = ACE::format_hexdump (buffer,
+ size,
+ buf,
+ sizeof (buf) / sizeof (ACE_TCHAR) - text_sz);
+
+ int sz = 0;
+
+ if (text)
+ sz = ACE_OS::sprintf (msg_buf,
+ ACE_LIB_TEXT ("%s - "),
+ text);
+
+ sz += ACE_OS::sprintf (msg_buf + sz,
+ ACE_LIB_TEXT ("HEXDUMP %d bytes"),
+ size);
+
+ if (len < size)
+ ACE_OS::sprintf (msg_buf + sz,
+ ACE_LIB_TEXT (" (showing first %d bytes)"),
+ len);
+
+ // Now print out the formatted buffer.
+ this->log (log_priority,
+ ACE_LIB_TEXT ("%s\n%s"),
+ msg_buf,
+ buf);
+
+ delete [] msg_buf;
+ return 0;
+}
+
+void
+ACE_Log_Msg::set (const char *filename,
+ int line,
+ int status,
+ int err,
+ int rs,
+ ACE_OSTREAM_TYPE *os,
+ ACE_Log_Msg_Callback *c)
+{
+ ACE_TRACE ("ACE_Log_Msg::set");
+ this->file (filename);
+ this->linenum (line);
+ this->op_status (status);
+ this->errnum (err);
+ this->restart (rs);
+ this->msg_ostream (os);
+ this->msg_callback (c);
+}
+
+void
+ACE_Log_Msg::conditional_set (const char *filename,
+ int line,
+ int status,
+ int err)
+{
+ this->conditional_values_.is_set_ = 1;
+ this->conditional_values_.file_ = filename;
+ this->conditional_values_.line_ = line;
+ this->conditional_values_.op_status_ = status;
+ this->conditional_values_.errnum_ = err;
+}
+
+void
+ACE_Log_Msg::dump (void) const
+{
+ ACE_TRACE ("ACE_Log_Msg::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("status_ = %d\n"), this->status_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nerrnum_ = %d\n"), this->errnum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlinenum_ = %d\n"), this->linenum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfile_ = %s\n"), this->file_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_ = %s\n"), this->msg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nrestart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nostream_ = %x\n"), this->ostream_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_callback_ = %x\n"),
+ this->msg_callback_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nprogram_name_ = %s\n"),
+ this->program_name_ ? this->program_name_
+ : ACE_LIB_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlocal_host_ = %s\n"),
+ this->local_host_ ? this->local_host_
+ : ACE_LIB_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npid_ = %d\n"), this->getpid ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nflags_ = %x\n"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntrace_depth_ = %d\n"),
+ this->trace_depth_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntrace_active_ = %d\n"),
+ this->trace_active_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntracing_enabled_ = %d\n"),
+ this->tracing_enabled_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npriority_mask_ = %x\n"),
+ this->priority_mask_));
+ if (this->thr_desc_ != 0 && this->thr_desc_->state () != 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthr_state_ = %d\n"),
+ this->thr_desc_->state ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_off_ = %d\n"), this->msg_off_));
+
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend ());
+
+ ACE_MT (ACE_Log_Msg_Manager::get_lock ()->dump ());
+ // Synchronize output operations.
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_Log_Msg::op_status (int status)
+{
+ this->status_ = status;
+}
+
+int
+ACE_Log_Msg::op_status (void)
+{
+ return this->status_;
+}
+
+void
+ACE_Log_Msg::restart (int r)
+{
+ this->restart_ = r;
+}
+
+int
+ACE_Log_Msg::restart (void)
+{
+ return this->restart_;
+}
+
+int
+ACE_Log_Msg::errnum (void)
+{
+ return this->errnum_;
+}
+
+void
+ACE_Log_Msg::errnum (int e)
+{
+ this->errnum_ = e;
+}
+
+int
+ACE_Log_Msg::linenum (void)
+{
+ return this->linenum_;
+}
+
+void
+ACE_Log_Msg::linenum (int l)
+{
+ this->linenum_ = l;
+}
+
+int
+ACE_Log_Msg::inc (void)
+{
+ return this->trace_depth_++;
+}
+
+int
+ACE_Log_Msg::dec (void)
+{
+ return --this->trace_depth_;
+}
+
+int
+ACE_Log_Msg::trace_depth (void)
+{
+ return this->trace_depth_;
+}
+
+void
+ACE_Log_Msg::trace_depth (int depth)
+{
+ this->trace_depth_ = depth;
+}
+
+int
+ACE_Log_Msg::trace_active (void)
+{
+ return this->trace_active_;
+}
+
+void
+ACE_Log_Msg::trace_active (int value)
+{
+ this->trace_active_ = value;
+}
+
+ACE_Thread_Descriptor *
+ACE_Log_Msg::thr_desc (void) const
+{
+ return this->thr_desc_;
+}
+
+void
+ACE_Log_Msg::thr_desc (ACE_Thread_Descriptor *td)
+{
+ this->thr_desc_ = td;
+
+ if (td != 0)
+ td->acquire_release ();
+}
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) && defined(ACE_LEGACY_MODE)
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_selector (void)
+{
+ return ACE_OS_Object_Manager::seh_except_selector ();
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_selector (ACE_SEH_EXCEPT_HANDLER n)
+{
+ return ACE_OS_Object_Manager::seh_except_selector (n);
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_handler (void)
+{
+ return ACE_OS_Object_Manager::seh_except_handler ();
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_handler (ACE_SEH_EXCEPT_HANDLER n)
+{
+ return ACE_OS_Object_Manager::seh_except_handler (n);
+}
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS && ACE_LEGACY_MODE */
+
+// Enable the tracing facility on a per-thread basis.
+
+void
+ACE_Log_Msg::start_tracing (void)
+{
+ this->tracing_enabled_ = 1;
+}
+
+// Disable the tracing facility on a per-thread basis.
+
+void
+ACE_Log_Msg::stop_tracing (void)
+{
+ this->tracing_enabled_ = 0;
+}
+
+int
+ACE_Log_Msg::tracing_enabled (void)
+{
+ return this->tracing_enabled_;
+}
+
+const char *
+ACE_Log_Msg::file (void)
+{
+ return this->file_;
+}
+
+void
+ACE_Log_Msg::file (const char *s)
+{
+ ACE_OS::strsncpy (this->file_, s, sizeof this->file_);
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::msg (void)
+{
+ return this->msg_ + ACE_Log_Msg::msg_off_;
+}
+
+void
+ACE_Log_Msg::msg (const ACE_TCHAR *m)
+{
+ ACE_OS::strsncpy (this->msg_, m,
+ (sizeof this->msg_ / sizeof (ACE_TCHAR)));
+}
+
+ACE_Log_Msg_Callback *
+ACE_Log_Msg::msg_callback (void) const
+{
+ return this->msg_callback_;
+}
+
+ACE_Log_Msg_Callback *
+ACE_Log_Msg::msg_callback (ACE_Log_Msg_Callback *c)
+{
+ ACE_Log_Msg_Callback *old = this->msg_callback_;
+ this->msg_callback_ = c;
+ return old;
+}
+
+ACE_OSTREAM_TYPE *
+ACE_Log_Msg::msg_ostream (void) const
+{
+ return this->ostream_;
+}
+
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m, int delete_ostream)
+{
+ this->delete_ostream_ = delete_ostream;
+ this->ostream_ = m;
+}
+
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m)
+{
+ this->ostream_ = m;
+}
+
+void
+ACE_Log_Msg::local_host (const ACE_TCHAR *s)
+{
+ if (s)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_ALLOCATOR (ACE_Log_Msg::local_host_, ACE_OS::strdup (s));
+ }
+ }
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::local_host (void) const
+{
+ return ACE_Log_Msg::local_host_;
+}
+
+pid_t
+ACE_Log_Msg::getpid (void) const
+{
+ if (ACE_Log_Msg::pid_ == -1)
+ ACE_Log_Msg::pid_ = ACE_OS::getpid ();
+
+ return ACE_Log_Msg::pid_;
+}
+
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
+ const char *,
+ ...)
+{
+ return this->log_priority_enabled (log_priority);
+}
+
+#if defined (ACE_USES_WCHAR)
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
+ const wchar_t *,
+ ...)
+{
+ return this->log_priority_enabled (log_priority);
+}
+#endif /* ACE_USES_WCHAR */
+
+// ****************************************************************
+
+void
+ACE_Log_Msg::init_hook (ACE_OS_Log_Msg_Attributes &attributes
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector
+ , ACE_SEH_EXCEPT_HANDLER handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+{
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ attributes.seh_except_selector_ = selector;
+ attributes.seh_except_handler_ = handler;
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ if (ACE_Log_Msg::exists ())
+ {
+ ACE_Log_Msg *inherit_log = ACE_LOG_MSG;
+ attributes.ostream_ = inherit_log->msg_ostream ();
+ attributes.priority_mask_ = inherit_log->priority_mask ();
+ attributes.tracing_enabled_ = inherit_log->tracing_enabled ();
+ attributes.restart_ = inherit_log->restart ();
+ attributes.trace_depth_ = inherit_log->trace_depth ();
+ }
+}
+
+#if defined (ACE_THREADS_DONT_INHERIT_LOG_MSG) || \
+ defined (ACE_HAS_MINIMAL_ACE_OS)
+# if defined (ACE_PSOS)
+// Unique file identifier
+static int ACE_PSOS_unique_file_id = 0;
+# endif /* ACE_PSOS */
+#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG) || ACE_HAS_MINIMAL_ACE_OS */
+
+void
+ACE_Log_Msg::inherit_hook (ACE_OS_Thread_Descriptor *thr_desc,
+ ACE_OS_Log_Msg_Attributes &attributes)
+{
+#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG) && \
+ !defined (ACE_HAS_MINIMAL_ACE_OS)
+ // Inherit the logging features if the parent thread has an
+ // <ACE_Log_Msg>. Note that all of the following operations occur
+ // within thread-specific storage.
+ ACE_Log_Msg *new_log = ACE_LOG_MSG;
+
+ // Note that we do not inherit the callback because this might have
+ // been allocated off of the stack of the original thread, in which
+ // case all hell would break loose...
+
+ if (attributes.ostream_)
+ {
+ new_log->msg_ostream (attributes.ostream_);
+ new_log->priority_mask (attributes.priority_mask_);
+
+ if (attributes.tracing_enabled_)
+ new_log->start_tracing ();
+
+ new_log->restart (attributes.restart_);
+ new_log->trace_depth (attributes.trace_depth_);
+ }
+
+ // @@ Now the TSS Log_Msg has been created, cache my thread
+ // descriptor in.
+
+ if (thr_desc != 0)
+ // This downcast is safe. We do it to avoid having to #include
+ // ace/Thread_Manager.h.
+ new_log->thr_desc (ACE_static_cast (ACE_Thread_Descriptor *,
+ thr_desc));
+ // Block the thread from proceeding until
+ // thread manager has thread descriptor ready.
+
+# else /* Don't inherit Log Msg */
+# if defined (ACE_PSOS)
+ //Create a special name for each thread...
+ char new_name[MAXPATHLEN]={"Ace_thread-"};
+ char new_id[2]={0,0}; //Now it's pre-terminated!
+
+ new_id[0] = '0' + (ACE_PSOS_unique_file_id++); //Unique identifier
+ ACE_OS::strcat(new_name, new_id);
+
+ //Initialize the task specific logger
+ ACE_LOG_MSG->open(new_name);
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) starting %s thread at %D\n"),new_name));
+# endif /* ACE_PSOS */
+#endif /* ! ACE_THREADS_DONT_INHERIT_LOG_MSG && ! ACE_HAS_MINIMAL_ACE_OS */
+}
diff --git a/ace/Logging/Log_Msg.h b/ace/Logging/Log_Msg.h
new file mode 100644
index 00000000000..48db78cb280
--- /dev/null
+++ b/ace/Logging/Log_Msg.h
@@ -0,0 +1,665 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_MSG_H
+#define ACE_LOG_MSG_H
+#include "ace/pre.h"
+
+// This stuff must come first to avoid problems with circular
+// headers...
+// ... but ACE_NDEBUG and ACE_NLOGGING can come from the config.h file, so
+// pull that one early.
+#include "ace/config-all.h"
+
+// The following ASSERT macro is courtesy of Alexandre Karev
+// <akg@na47sun05.cern.ch>.
+#if defined (ACE_NDEBUG)
+#define ACE_ASSERT(x)
+#elif !defined (ACE_ASSERT)
+#define ACE_ASSERT(X) \
+ do { if(!(X)) { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->set (__FILE__, __LINE__, -1, __ace_error, ace___->restart (), \
+ ace___->msg_ostream (), ace___->msg_callback ()); \
+ ace___->log (LM_ERROR, ACE_LIB_TEXT ("ACE_ASSERT: file %N, line %l assertion failed for '%s'.%a\n"), #X, -1); \
+ } } while (0)
+#endif /* ACE_NDEBUG */
+
+#if defined (ACE_NLOGGING)
+#define ACE_HEX_DUMP(X) do {} while (0)
+#define ACE_RETURN(Y) do { return (Y); } while (0)
+#define ACE_ERROR_RETURN(X, Y) return (Y)
+#define ACE_ERROR_BREAK(X) { break; }
+#define ACE_ERROR(X) do {} while (0)
+#define ACE_DEBUG(X) do {} while (0)
+#define ACE_ERROR_INIT(VALUE, FLAGS)
+#else
+#define ACE_HEX_DUMP(X) \
+ do { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
+ ace___->log_hexdump X; \
+ } while (0)
+#define ACE_RETURN(Y) \
+ do { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->set (__FILE__, __LINE__, Y, __ace_error, ace___->restart (), \
+ ace___->msg_ostream (), ace___->msg_callback ()); \
+ return Y; \
+ } while (0)
+#define ACE_ERROR_RETURN(X, Y) \
+ do { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, Y, __ace_error); \
+ ace___->log X; \
+ return Y; \
+ } while (0)
+#define ACE_ERROR(X) \
+ do { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, -1, __ace_error); \
+ ace___->log X; \
+ } while (0)
+#define ACE_DEBUG(X) \
+ do { \
+ int __ace_error = ACE_OS::last_error (); \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
+ ace___->log X; \
+ } while (0)
+#define ACE_ERROR_INIT(VALUE, FLAGS) \
+ do { \
+ ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
+ ace___->set_flags (FLAGS); ace___->op_status (VALUE); \
+ } while (0)
+#define ACE_ERROR_BREAK(X) { ACE_ERROR (X); break; }
+#endif /* ACE_NLOGGING */
+
+#include "ace/Logging/Log_Record.h"
+#include "ace/OS/OS_Log_Msg_Attributes.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (__Lynx__)
+# undef STDERR
+#endif /* __Lynx__ */
+
+#if defined (THREAD)
+// This workaround is necessary for nasty libraries that #define
+// THREAD 1.
+#define ACE_THREAD_HACK THREAD
+#undef THREAD
+#endif /* THREAD */
+
+class ACE_Log_Msg_Callback;
+
+// ****************************************************************
+
+#define ACE_LOG_MSG ACE_Log_Msg::instance ()
+
+// Forward declaration
+class ACE_Thread_Descriptor;
+
+/**
+ * @class ACE_Log_Msg
+ *
+ * @brief Provides a variable length argument message logging
+ * abstraction.
+ *
+ * This class is very flexible since it allows formatted error
+ * messages to be printed in a thread-safe manner to various
+ * locations, such as stdout, stderr, cerr, a distributed logger, etc.
+ * The current message is also kept in a thread-specific storage
+ * location (i.e., there is one ACE_Log_Msg object per-thread), which
+ * can be used to communicate errors between framework methods and
+ * callers. A message is logged by the log() method, only if the
+ * message priority is currently enabled. Moreover, only the current
+ * log message is stored here -- it will be overwritten by the
+ * subsequent call to <log>.
+ *
+ * The ACE_Log_Msg class uses two priority masks to control its
+ * logging behavior. The <priority_mask_> object attribute is thread
+ * specific and specifies the priority levels logged by the thread.
+ * The <process_priority_mask_> class attribute is not thread-specific
+ * and specifies the priority levels that will be logged by all
+ * threads in the process. By default, all levels are disabled for
+ * <priority_mask_> and all levels are enabled for
+ * <process_priority_mask_> (i.e. the process-wide mask controls
+ * the settings, and each instance can expand on it if desired).
+ * Both priority masks can be modified using the priority_mask()
+ * method of this class.
+ */
+class ACE_Export ACE_Log_Msg
+{
+
+public:
+ // Logger Flags.
+ enum
+ {
+ /// Write messages to stderr.
+ STDERR = 1,
+ /// Write messages to the local client logger deamon.
+ LOGGER = 2,
+ /// Write messages to the ostream * stored in thread-specific
+ /// storage.
+ OSTREAM = 4,
+ /// Write messages to the callback object.
+ MSG_CALLBACK = 8,
+ /// Display messages in a verbose manner.
+ VERBOSE = 16,
+ /// Display messages in a less verbose manner (i.e., only print
+ /// information that can change between calls).
+ VERBOSE_LITE = 32,
+ /// Do not print messages at all (just leave in thread-specific
+ /// storage for later inspection).
+ SILENT = 64,
+ /// Write messages to the system's event log.
+ SYSLOG = 128
+ };
+
+ // = Initialization and termination routines.
+
+ /// Returns a pointer to the Singleton.
+ static ACE_Log_Msg *instance (void);
+
+ /// Returns non-null if an ACE_Log_Msg exists for the calling thread.
+ static int exists (void);
+
+ /// Returns the current program name used for logging.
+ static const ACE_TCHAR * program_name (void);
+ /// Clears the flag from the default priority mask used to
+ /// initialize ACE_Log_Msg instances.
+ static void disable_debug_messages (ACE_Log_Priority priority = LM_DEBUG);
+
+ /// Sets the flag in the default priority mask used to initialize
+ /// ACE_Log_Msg instances.
+ static void enable_debug_messages (ACE_Log_Priority priority = LM_DEBUG);
+
+ /// Initialize logger.
+ ACE_Log_Msg (void);
+
+ /// cleanup logger.
+ ~ACE_Log_Msg (void);
+
+ /// Initialize the ACE logging facility.
+ /**
+ * Initialize the ACE logging facility. Supplies the program name
+ * that is available to each logging message call. Default arguments
+ * set up logging to STDERR only.
+ *
+ * @param prog_name The name of the calling program.
+ * @param flags A bitwise-or of options flags used to set the
+ * initial behavior and logging sink(s). (see the
+ * enum above for the valid values).
+ * @param logger_key The name of ACE_FIFO rendezvous point where the
+ * local client logger daemon is listening for logging
+ * messages. Only meaningful if the LOGGER bit is
+ * set in the <flags> argument.
+ */
+ int open (const ACE_TCHAR *prog_name,
+ u_long options_flags = ACE_Log_Msg::STDERR,
+ const ACE_TCHAR *logger_key = 0);
+
+ // = Set/get the options flags.
+
+ /**
+ * Enable the bits in the logger's options flags.
+ * Disable the bits in the logger's options flags.
+ * Return the bits in the logger's options flags.
+ */
+ void set_flags (u_long f);
+ void clr_flags (u_long f);
+ u_long flags (void);
+
+ /** @name Allow apps to acquire and release internal synchronization
+ * lock
+ *
+ * This lock is used internally by the <ACE_Log_Msg>
+ * implementation. By exporting the lock, applications can hold the
+ * lock atomically over a number of calls to <ACE_Log_Msg>.
+ */
+ //@{
+
+ /// Acquire the internal lock.
+ int acquire (void);
+
+ /// Release the internal lock.
+ int release (void);
+ //@}
+
+ /// Call after doing a <fork> to resynchronize the process id and
+ /// <program_name> variables.
+ void sync (const ACE_TCHAR *program_name);
+
+ // = Set/get methods. Note that these are non-static and thus will
+ // be thread-specific.
+
+ /// Set the result of the operation status (by convention, -1 means
+ /// error).
+ void op_status (int status);
+
+ /// Get the result of the operation status (by convention, -1 means
+ /// error).
+ int op_status (void);
+
+ /// Set the value of the errnum (by convention this corresponds to
+ /// errno).
+ void errnum (int);
+
+ /// Get the value of the errnum (by convention this corresponds to
+ /// errno).
+ int errnum (void);
+
+ /// Set the line number where an error occurred.
+ void linenum (int);
+
+ /// Get the line number where an error occurred.
+ int linenum (void);
+
+ /// Set the file name where an error occurred.
+ void file (const char *);
+
+ /// Get the file name where an error occurred.
+ const char *file (void);
+
+ /// Set the message that describes what type of error occurred.
+ void msg (const ACE_TCHAR *);
+
+ /// Get the message that describes what type of error occurred.
+ const ACE_TCHAR *msg (void);
+
+ /// Set the field that indicates whether interrupted calls should be
+ /// restarted.
+ void restart (int);
+
+ /// Get the field that indicates whether interrupted calls should be
+ /// restarted.
+ int restart (void);
+
+ // = Notice that the following two function is equivalent to
+ // "void msg_ostream (HANDLE)" and "HANDLE msg_ostream (void)"
+ // on Windows CE. There is no <iostream.h> support on CE.
+
+ /// Update the ostream without overwriting the delete_ostream_ flag.
+ void msg_ostream (ACE_OSTREAM_TYPE *);
+
+ /**
+ * delete_stream == 1, forces Log_Msg.h to delete the stream in
+ * its own ~dtor (assumes control of the stream)
+ * use only with proper ostream (eg: fstream), not (cout, cerr)
+ */
+ void msg_ostream (ACE_OSTREAM_TYPE *, int delete_ostream);
+
+ /// Get the ostream that is used to print error messages.
+ ACE_OSTREAM_TYPE *msg_ostream (void) const;
+
+ /**
+ * Set a new callback object and return the existing callback to
+ * allow "chaining". Note that <ACE_Log_Msg_Callback>s are not
+ * inherited when spawning a new thread, so you'll need to reset
+ * them in each thread.
+ */
+ ACE_Log_Msg_Callback *msg_callback (ACE_Log_Msg_Callback *c);
+ ACE_Log_Msg_Callback *msg_callback (void) const;
+
+ // = Nesting depth increment and decrement.
+ int inc (void);
+ int dec (void);
+
+ // = Get/set trace depth.
+ int trace_depth (void);
+ void trace_depth (int);
+
+ // = Get/set trace active status.
+ int trace_active (void);
+ void trace_active (int value);
+
+ /// Get the TSS thread descriptor.
+ ACE_Thread_Descriptor *thr_desc (void) const;
+
+ /**
+ * Set the TSS thread descriptor. This method will call
+ * td->acquire_release to block execution until this call
+ * return.
+ */
+ void thr_desc (ACE_Thread_Descriptor *td);
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) && defined(ACE_LEGACY_MODE)
+ // These functions are disabled without ACE_LEGACY_MODE
+ // because the *semantics* have changed (the objects are no longer
+ // TSS).
+ /// Get/Set TSS exception action.
+ /// NOTE: The action is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector (void);
+ ACE_SEH_EXCEPT_HANDLER seh_except_selector (ACE_SEH_EXCEPT_HANDLER);
+
+ /// Get/Set TSS exception handler.
+ /// NOTE: The handler is no longer TSS, they are global!
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler (void);
+ ACE_SEH_EXCEPT_HANDLER seh_except_handler (ACE_SEH_EXCEPT_HANDLER);
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS && ACE_LEGACY_MODE */
+
+ // = Stop/start/query tracing status on a per-thread basis...
+ void stop_tracing (void);
+ void start_tracing (void);
+ int tracing_enabled (void);
+
+ typedef enum
+ {
+ PROCESS = 0,
+ THREAD = 1
+ } MASK_TYPE;
+
+ // = Get/set the priority mask.
+ /// Get the current <ACE_Log_Priority> mask.
+ /// Set the <ACE_Log_Priority> mask, returns original mask.
+ u_long priority_mask (MASK_TYPE = THREAD);
+ u_long priority_mask (u_long, MASK_TYPE = THREAD);
+
+ /// Return true if the requested priority is enabled.
+ int log_priority_enabled (ACE_Log_Priority log_priority);
+
+ /// Return true if the requested priority is enabled.
+ int log_priority_enabled (ACE_Log_Priority log_priority,
+ const char *,
+ ...);
+
+#if defined (ACE_USES_WCHAR)
+ // We are not using ACE_TCHAR for this since ACE_HEX_DUMP
+ // doesn't take in a ACE_TCHAR. log_hexdump takes in a char
+ // string, so this must be able to take in a char string even
+ // when using ACE_USES_WCHAR.
+ /// Return true if the requested priority is enabled.
+ int log_priority_enabled (ACE_Log_Priority log_priority,
+ const wchar_t *,
+ ...);
+#endif /* ACE_USES_WCHAR */
+
+ /// Optimize reading of the pid (avoids a system call if the value is
+ /// cached...).
+ pid_t getpid (void) const;
+
+ // = Set/get the name of the local host.
+ const ACE_TCHAR *local_host (void) const;
+ void local_host (const ACE_TCHAR *);
+
+ /**
+ * Set the line number, file name, operational status, error number,
+ * restart flag, ostream, and the callback object. This combines
+ * all the other set methods into a single method.
+ */
+ void set (const char *file,
+ int line,
+ int op_status = -1,
+ int errnum = 0,
+ int restart = 1,
+ ACE_OSTREAM_TYPE *os = 0,
+ ACE_Log_Msg_Callback *c = 0);
+
+ /// These values are only actually set if the requested priority is
+ /// enabled.
+ void conditional_set (const char *file,
+ int line,
+ int op_status,
+ int errnum);
+
+ /**
+ * Format a message to the thread-safe ACE logging mechanism. Valid
+ * options (prefixed by '%', as in printf format strings) include:
+ * + 'A': print an ACE_timer_t value (which could be either double
+ * or ACE_UINT32.)
+ * + 'a': abort the program at this point abruptly.
+ * + 'c': print a character
+ * + 'C': print a character string
+ * + 'i', 'd': print a decimal number
+ * + 'I': indent according to nesting depth (obtained from
+ * <ACE_Trace::get_nesting_indent>).
+ * + 'e', 'E', 'f', 'F', 'g', 'G': print a double
+ * + 'l': print line number where an error occurred.
+ * + 'M': print the name of the priority of the message.
+ * + 'm': return the message corresponding to errno value, e.g., as
+ * done by strerror()
+ * + 'N': print file name where the error occurred.
+ * + 'n': print the name of the program (or "<unknown>" if not set)
+ * + 'o': print as an octal number
+ * + 'P': print out the current process id
+ * + 'p': print out the appropriate errno message from sys_errlist,
+ * e.g., as done by perror()
+ * + 'Q': print out the uint64 number
+ * + 'r': call the function pointed to by the corresponding argument
+ * + 'R': print return status
+ * + 'S': print out the appropriate _sys_siglist entry corresponding
+ * to var-argument.
+ * + 's': print out a character string
+ * + 'T': print timestamp in hour:minute:sec:usec format.
+ * + 'D': print timestamp in month/day/year hour:minute:sec:usec format.
+ * + 't': print thread id (1 if single-threaded)
+ * + 'u': print as unsigned int
+ * + 'w': prints a wide character
+ * + 'W': print a wide character string
+ * + 'X', 'x': print as a hex number
+ * + '%': print out a single percent sign, '%'
+ */
+ ssize_t log (ACE_Log_Priority priority, const ACE_TCHAR *format, ...);
+
+#if defined (ACE_HAS_WCHAR)
+ ssize_t log (ACE_Log_Priority priority, const ACE_ANTI_TCHAR *format, ...);
+#endif /* ACE_HAS_WCHAR */
+
+ /**
+ * An alternative logging mechanism that makes it possible to
+ * integrate variable argument lists from other logging mechanisms
+ * into the ACE mechanism.
+ */
+ ssize_t log (const ACE_TCHAR *format,
+ ACE_Log_Priority priority,
+ va_list argp);
+
+ /// Log a custom built log record to the currently enabled logging
+ /// sinks.
+ ssize_t log (ACE_Log_Record &log_record,
+ int suppress_stderr = 0);
+
+ /**
+ * Method to log hex dump. This is useful for debugging. Calls
+ * <log> to do the actual print, but formats first to make the chars
+ * printable.
+ */
+ int log_hexdump (ACE_Log_Priority log_priority,
+ const char *buffer,
+ int size,
+ const ACE_TCHAR *text = 0);
+
+ static void init_hook (ACE_OS_Log_Msg_Attributes &attributes
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector = 0
+ , ACE_SEH_EXCEPT_HANDLER handler = 0
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ /**
+ * Init hook, create a Log_Msg_Attribute object, initialize its
+ * attributes from the TSS Log_Msg and save the object in the
+ * <attributes> argument
+ */
+ );
+
+ /**
+ * Inherit hook, the <attributes> field is a Log_Msg_Attribute
+ * object, invoke the <inherit_log_msg> method on it, then destroy
+ * it and set the <attribute> argument to 0
+ */
+ static void inherit_hook (ACE_OS_Thread_Descriptor *thr_desc,
+ ACE_OS_Log_Msg_Attributes &attributes);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Status of operation (-1 means failure, >= 0 means success).
+ int status_;
+
+ /// Type of error that occurred (see <sys/errno.h>).
+ int errnum_;
+
+ /// Line number where the error occurred.
+ int linenum_;
+
+ /// File where the error occurred.
+ char file_[MAXPATHLEN + 1];
+
+ /// The log message, which resides in thread-specific storage. Note
+ /// that only the current log message is stored here -- it will be
+ /// overwritten by the subsequent call to <log>.
+ ACE_TCHAR msg_[ACE_Log_Record::MAXLOGMSGLEN + 1]; // Add one for NUL-terminator.
+
+ /// Indicates whether we should restart system calls that are
+ /// interrupted.
+ int restart_;
+
+ /// The ostream where logging messages can be written.
+ ACE_OSTREAM_TYPE *ostream_;
+
+ /// The callback object.
+ ACE_Log_Msg_Callback *msg_callback_;
+
+ /// Depth of the nesting for printing traces.
+ int trace_depth_;
+
+ /// Are we already within an ACE_Trace constructor call?
+ int trace_active_;
+
+ /// Are we allowing tracing in this thread?
+ int tracing_enabled_;
+
+ /// Are we deleting this ostream?
+ int delete_ostream_;
+
+ /**
+ * If we're running in the context of an <ACE_Thread_Manager> this
+ * will point to the thread descriptor adapter which holds the
+ * thread descriptor of the thread. This can be used to repidly
+ * access all thread data kept in <ACE_Thread_Descriptor>.
+ */
+ ACE_Thread_Descriptor *thr_desc_;
+
+ /**
+ * Keeps track of all the per-thread <ACE_Log_Priority> values that
+ * are currently enabled. Default is for all logging priorities to
+ * be _disabled_.
+ */
+ u_long priority_mask_;
+
+ // = The following fields are *not* kept in thread-specific storage.
+
+ // We only want one instance for the entire process!
+
+ /**
+ * Keeps track of all the per-process <ACE_Log_Priority> values that
+ * are currently enabled. Default is for all logging priorities to
+ * be enabled.
+ */
+ static u_long process_priority_mask_;
+
+ /// Records the program name.
+ static const ACE_TCHAR *program_name_;
+
+ /// Name of the local host (used when printing messages).
+ static const ACE_TCHAR *local_host_;
+
+ /// Process id of the current process.
+ static pid_t pid_;
+
+ /// Options flags.
+ static u_long flags_;
+
+ /// Offset of msg_[].
+ static int msg_off_;
+
+ /**
+ * Number of existing Log_Msg instances; when 0, delete program/host
+ * names
+ * Priority mask to use for each new instance
+ */
+ static int instance_count_;
+ static u_long default_priority_mask_;
+
+ // Anonymous struct since there will only be one instance. This
+ // struct keeps information stored away in case we actually end up
+ // calling log() if the log priority is correct.
+ struct
+ {
+ int is_set_;
+ const char *file_;
+ int line_;
+ int op_status_;
+ int errnum_;
+ } conditional_values_;
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ static int key_created_;
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ static ACE_thread_key_t log_msg_tss_key_;
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ACE_MT_SAFE */
+
+ /// For cleanup, at program termination.
+ static void close (void);
+
+ /// Decouple the OS layer from the Log_Msg layer.
+ static void sync_hook (const ACE_TCHAR *prg_name);
+
+ /// Return the TSS singleton thread descriptor
+ static ACE_OS_Thread_Descriptor *thr_desc_hook (void);
+
+ friend void ACE_OS::cleanup_tss (const u_int);
+
+ // = Disallow these operations.
+ ACE_Log_Msg &operator= (const ACE_Log_Msg &);
+ ACE_Log_Msg (const ACE_Log_Msg &);
+};
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+/* static */
+# if defined (ACE_HAS_THR_C_DEST)
+# define LOCAL_EXTERN_PREFIX extern "C"
+# else
+# define LOCAL_EXTERN_PREFIX
+# endif /* ACE_HAS_THR_C_DEST */
+LOCAL_EXTERN_PREFIX
+void
+ACE_TSS_cleanup (void *ptr);
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ACE_MT_SAFE */
+
+#if defined (ACE_THREAD_HACK)
+#define THREAD ACE_THREAD_HACK
+#undef ACE_THREAD_HACK
+#endif /* ACE_THREAD_HACK */
+
+#if defined(ACE_LEGACY_MODE)
+#include "ace/Logging/Log_Msg_Callback.h"
+#endif /* ACE_LEGACY_MODE */
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_H */
diff --git a/ace/Logging/Log_Msg_Backend.cpp b/ace/Logging/Log_Msg_Backend.cpp
new file mode 100644
index 00000000000..8e4ae6208f3
--- /dev/null
+++ b/ace/Logging/Log_Msg_Backend.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/Log_Msg_Backend.h"
+
+ACE_RCSID(ace, Log_Msg_Backend, "$Id$")
+
+ACE_Log_Msg_Backend::~ACE_Log_Msg_Backend (void)
+{
+}
diff --git a/ace/Logging/Log_Msg_Backend.h b/ace/Logging/Log_Msg_Backend.h
new file mode 100644
index 00000000000..bc8e867018a
--- /dev/null
+++ b/ace/Logging/Log_Msg_Backend.h
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg_Backend.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOG_MSG_BACKEND_H
+#define ACE_LOG_MSG_BACKEND_H
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class ACE_Log_Record;
+
+/**
+ * @class ACE_Log_Msg_Backend
+ *
+ * @brief Define the interface for ACE_Log_Msg backend strategies.
+ *
+ * The ACE_Log_Msg class can log to multiple backend strategies, for
+ * example, some send messages to a remote logger, others dump to a
+ * file, or simply to stderr. In the future we could define
+ * interfaces that log to the syslog daemon (on UNIX), the Event log
+ * (on NT) a temporary ring buffer, etc.
+ */
+class ACE_Export ACE_Log_Msg_Backend
+{
+public:
+ /// No-op virtual destructor.
+ virtual ~ACE_Log_Msg_Backend (void);
+
+ /// Open a new connection
+ virtual int open (const ACE_TCHAR *logger_key) = 0;
+
+ /*
+ * Reset the backend. When changing the logging destination the
+ * backend may need to properly disconnect from the remote logging
+ * daemon and reclaim some local resources. But we try to reduce
+ * the number of local allocations/deallocations.
+ */
+ virtual int reset (void) = 0;
+
+ /// Close the backend completely.
+ virtual int close (void) = 0;
+
+ /// Backend routine. This is called when we want to log a message.
+ /// Since this routine is pure virtual, it must be overwritten by the
+ /// subclass.
+ virtual int log (ACE_Log_Record &log_record) = 0;
+};
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_BACKEND_H */
diff --git a/ace/Logging/Log_Msg_Callback.cpp b/ace/Logging/Log_Msg_Callback.cpp
new file mode 100644
index 00000000000..c2ab8da127c
--- /dev/null
+++ b/ace/Logging/Log_Msg_Callback.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/Log_Msg_Callback.h"
+
+ACE_RCSID(ace, Log_Msg_Callback, "$Id$")
+
+ACE_Log_Msg_Callback::~ACE_Log_Msg_Callback (void)
+{
+}
diff --git a/ace/Logging/Log_Msg_Callback.h b/ace/Logging/Log_Msg_Callback.h
new file mode 100644
index 00000000000..b9c833745ad
--- /dev/null
+++ b/ace/Logging/Log_Msg_Callback.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg_Callback.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_MSG_CALLBACK_H
+#define ACE_LOG_MSG_CALLBACK_H
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class ACE_Log_Record;
+
+/**
+ * @class ACE_Log_Msg_Callback
+ *
+ * @brief An interface class used to get logging callbacks.
+ *
+ * Users who are interested in getting the logging messages
+ * directly, can subclass this interface and override the log()
+ * method. They must then register their subclass with the
+ * Log_Msg class and make sure that they turn on the
+ * ACE_Log_Msg::MSG_CALLBACK flag.
+ *
+ * Your <log> routine is called with an instance of
+ * ACE_Log_Record. From this class, you can get the log
+ * message, the verbose log message, message type, message
+ * priority, and so on.
+ *
+ * Remember that there is one Log_Msg object per thread.
+ * Therefore, you may need to register your callback object with
+ * many <ACE_Log_Msg> objects (and have the correct
+ * synchronization in the <log> method) or have a separate
+ * callback object per Log_Msg object. Moreover,
+ * <ACE_Log_Msg_Callbacks> are not inherited when a new thread
+ * is spawned because it might have been allocated off of the
+ * stack of the original thread, in which case all hell would
+ * break loose... Therefore, you'll need to reset these in each
+ * new thread.
+ */
+class ACE_Export ACE_Log_Msg_Callback
+{
+public:
+ /// No-op virtual destructor.
+ virtual ~ACE_Log_Msg_Callback (void);
+
+ /// Callback routine. This is called when we want to log a message.
+ /// Since this routine is pure virtual, it must be overwritten by the
+ /// subclass.
+ virtual void log (ACE_Log_Record &log_record) = 0;
+};
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_CALLBACK_H */
diff --git a/ace/Logging/Log_Msg_IPC.cpp b/ace/Logging/Log_Msg_IPC.cpp
new file mode 100644
index 00000000000..9d90638395e
--- /dev/null
+++ b/ace/Logging/Log_Msg_IPC.cpp
@@ -0,0 +1,72 @@
+// $Id$
+
+#include "ace/Log_Msg_IPC.h"
+#include "ace/Log_Record.h"
+
+ACE_RCSID(ace, Log_Msg_IPC, "$Id$")
+
+ACE_Log_Msg_IPC::ACE_Log_Msg_IPC (void)
+{
+}
+
+ACE_Log_Msg_IPC::~ACE_Log_Msg_IPC (void)
+{
+ (void) this->close ();
+}
+
+int
+ACE_Log_Msg_IPC::open (const ACE_TCHAR *logger_key)
+{
+ ACE_LOG_MSG_IPC_CONNECTOR con;
+ return con.connect (this->message_queue_,
+ ACE_LOG_MSG_IPC_ADDR (logger_key));
+}
+
+int
+ACE_Log_Msg_IPC::reset (void)
+{
+ if (this->message_queue_.get_handle () != ACE_INVALID_HANDLE)
+ {
+ // If we don't do this, handles aren't reused on Win32 and the
+ // server eventually crashes!
+#if defined (ACE_WIN32)
+ ACE_INT32 dummy = ~0;
+ this->message_queue_.send_n ((const void *) &dummy,
+ sizeof (ACE_INT32));
+#endif /* ACE_WIN32 */
+ return this->close ();
+ }
+ return 0;
+}
+
+int
+ACE_Log_Msg_IPC::close (void)
+{
+ return this->message_queue_.close ();
+}
+
+int
+ACE_Log_Msg_IPC::log (ACE_Log_Record &log_record)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ ACE_Str_Buf log_msg (ACE_static_cast (void *,
+ &log_record),
+ ACE_static_cast (int,
+ log_record.length ()));
+
+ // Try to use the <putpmsg> API if possible in order to
+ // ensure correct message queueing according to priority.
+ return
+ this->message_queue_.send
+ (ACE_static_cast (const ACE_Str_Buf *, 0),
+ &log_msg,
+ ACE_static_cast (int, log_record.priority ()),
+ MSG_BAND);
+#else
+ // We're running over sockets, so we'll need to indicate the
+ // number of bytes to send.
+ return
+ this->message_queue_.send_n ((void *) &log_record,
+ log_record.length ());
+#endif /* ACE_HAS_STREAM_PIPES */
+}
diff --git a/ace/Logging/Log_Msg_IPC.h b/ace/Logging/Log_Msg_IPC.h
new file mode 100644
index 00000000000..b9ab8885fcf
--- /dev/null
+++ b/ace/Logging/Log_Msg_IPC.h
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg_IPC.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan <coryan@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_MSG_LOGGER_H
+#define ACE_LOG_MSG_LOGGER_H
+#include "ace/pre.h"
+
+#include "ace/Log_Msg_Backend.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// IPC conduit between sender and client daemon. This should be
+// included in the <ACE_Log_Msg> class, but due to "order of include"
+// problems it can't be...
+#if defined (ACE_HAS_STREAM_PIPES)
+# include "ace/SPIPE_Connector.h"
+typedef ACE_SPIPE_Stream ACE_LOG_MSG_IPC_STREAM;
+typedef ACE_SPIPE_Connector ACE_LOG_MSG_IPC_CONNECTOR;
+typedef ACE_SPIPE_Addr ACE_LOG_MSG_IPC_ADDR;
+#else
+# include "ace/SOCK_Connector.h"
+typedef ACE_SOCK_Stream ACE_LOG_MSG_IPC_STREAM;
+typedef ACE_SOCK_Connector ACE_LOG_MSG_IPC_CONNECTOR;
+typedef ACE_INET_Addr ACE_LOG_MSG_IPC_ADDR;
+#endif /* ACE_HAS_STREAM_PIPES */
+
+/// Defines the interfaces for ACE_Log_Msg backend.
+/**
+ * Implement an ACE_Log_Msg_Backend that logs to a remote logging
+ * process.
+ */
+class ACE_Export ACE_Log_Msg_IPC : public ACE_Log_Msg_Backend
+{
+public:
+ /// Constructor
+ ACE_Log_Msg_IPC (void);
+
+ /// Destructor
+ virtual ~ACE_Log_Msg_IPC (void);
+
+ /// Open a new connection
+ virtual int open (const ACE_TCHAR *logger_key);
+ virtual int reset (void);
+ virtual int close (void);
+ virtual int log (ACE_Log_Record &log_record);
+
+private:
+ ACE_LOG_MSG_IPC_STREAM message_queue_;
+};
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_H */
diff --git a/ace/Logging/Log_Msg_NT_Event_Log.cpp b/ace/Logging/Log_Msg_NT_Event_Log.cpp
new file mode 100644
index 00000000000..60bc8eed684
--- /dev/null
+++ b/ace/Logging/Log_Msg_NT_Event_Log.cpp
@@ -0,0 +1,143 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
+
+#include "ace/Log_Msg_NT_Event_Log.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Record.h"
+
+ACE_RCSID(ace, Log_Msg_NT_Event_Log, "$Id$")
+
+ACE_Log_Msg_NT_Event_Log::ACE_Log_Msg_NT_Event_Log (void)
+ : evlog_handle_(0)
+{
+}
+
+ACE_Log_Msg_NT_Event_Log::~ACE_Log_Msg_NT_Event_Log (void)
+{
+ (void) this->close ();
+}
+
+int
+ACE_Log_Msg_NT_Event_Log::open (const ACE_TCHAR *logger_key)
+{
+ // ACE's "resource module" contains the message resource required
+ // for event logging.
+ ACE_TCHAR msg_file [MAXPATHLEN];
+
+ if (!ACE_TEXT_GetModuleFileName (ACE_OS::get_win32_resource_module (),
+ msg_file,
+ MAXPATHLEN))
+ return -1;
+ int msg_file_length = ACE_OS::strlen (msg_file);
+
+ // Information is stored in the registry at a location based on the
+ // program name.
+ ACE_TCHAR reg_key [MAXPATHLEN];
+ ACE_OS::strcpy (reg_key,
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"));
+ int reg_key_length = ACE_OS::strlen(reg_key);
+ ACE_OS::strncat (reg_key,
+ logger_key ? logger_key : ACE_Log_Msg::program_name (),
+ MAXPATHLEN - reg_key_length);
+
+ // Add the event source to the registry. Note that if this fails it
+ // is not fatal. The application will still be able to write entries
+ // to the event log, they just won't be formatted correctly.
+ HKEY hkey;
+ ACE_TEXT_RegCreateKey (HKEY_LOCAL_MACHINE,
+ reg_key,
+ &hkey);
+ DWORD flags = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ ACE_TEXT_RegSetValueEx (hkey,
+ ACE_LIB_TEXT ("TypesSupported"),
+ 0,
+ REG_DWORD,
+ (LPBYTE) &flags,
+ sizeof (DWORD));
+ ACE_TEXT_RegSetValueEx (hkey,
+ ACE_LIB_TEXT ("EventMessageFile"),
+ 0,
+ REG_SZ,
+ (LPBYTE) msg_file,
+ msg_file_length + 1);
+ RegCloseKey (hkey);
+
+ // Obtain a handle to the event source.
+ this->evlog_handle_ = ACE_TEXT_RegisterEventSource (0, ACE_Log_Msg::program_name ());
+ return this->evlog_handle_ ? 0 : -1;
+}
+
+int
+ACE_Log_Msg_NT_Event_Log::reset (void)
+{
+ return this->close ();
+}
+
+int
+ACE_Log_Msg_NT_Event_Log::close (void)
+{
+ if (DeregisterEventSource (this->evlog_handle_))
+ {
+ this->evlog_handle_ = 0;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int
+ACE_Log_Msg_NT_Event_Log::log (ACE_Log_Record &log_record)
+{
+ // Make a copy of the log text and replace any newlines with
+ // spaces. Newline characters do not appear correctly in the event
+ // viewer.
+ const ACE_TCHAR* src_msg_data = log_record.msg_data ();
+ ACE_TCHAR msg_data [ACE_Log_Record::MAXLOGMSGLEN];
+
+ for (long i = 0; i < log_record.length (); ++i)
+ {
+ if (src_msg_data[i] == '\n')
+ msg_data[i] = ' ';
+ else
+ msg_data[i] = src_msg_data[i];
+ }
+
+ // Map the ACE log record type to an event log type.
+ WORD event_type;
+ switch (log_record.type ())
+ {
+ case LM_STARTUP:
+ case LM_SHUTDOWN:
+ case LM_TRACE:
+ case LM_DEBUG:
+ case LM_INFO:
+ event_type = EVENTLOG_INFORMATION_TYPE;
+ break;
+ case LM_NOTICE:
+ case LM_WARNING:
+ event_type = EVENTLOG_WARNING_TYPE;
+ break;
+ case LM_ERROR:
+ case LM_CRITICAL:
+ case LM_ALERT:
+ case LM_EMERGENCY:
+ default:
+ event_type = EVENTLOG_ERROR_TYPE;
+ break;
+ }
+
+ // Send the log message to the system event log.
+ const ACE_TCHAR* msgs [1];
+ msgs[0] = msg_data;
+
+ if (ACE_TEXT_ReportEvent (this->evlog_handle_,
+ event_type, 0, 0, 0, 1, 0, msgs, 0) == 0)
+ return -1;
+ else
+ return 0;
+}
+
+#endif /* ACE_WIN32 */
diff --git a/ace/Logging/Log_Msg_NT_Event_Log.h b/ace/Logging/Log_Msg_NT_Event_Log.h
new file mode 100644
index 00000000000..4e2b8cf6697
--- /dev/null
+++ b/ace/Logging/Log_Msg_NT_Event_Log.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg_NT_Event_Log.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_MSG_NT_EVENT_LOG_H
+#define ACE_LOG_MSG_NT_EVENT_LOG_H
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+
+#include "ace/Log_Msg_Backend.h"
+
+/**
+ * @class ACE_Log_Msg_NT_Event_Log
+ *
+ * @brief Implements an ACE_Log_Msg_Backend that logs to the WinNT system
+ * event log.
+ */
+class ACE_Export ACE_Log_Msg_NT_Event_Log : public ACE_Log_Msg_Backend
+{
+public:
+ /// Constructor
+ ACE_Log_Msg_NT_Event_Log (void);
+
+ /// Destructor
+ virtual ~ACE_Log_Msg_NT_Event_Log (void);
+
+ /// Open a new event log.
+ /**
+ * Initialize the event logging facility.
+ * @param logger_key The name of the calling program. This name is
+ * used in the Source field of the event log. If
+ * it is 0 (no name), the application name as
+ * returned from ACE_Log_Msg::program_name() is used.
+ */
+ virtual int open (const ACE_TCHAR *logger_key);
+
+ /// Reset the backend.
+ virtual int reset (void);
+
+ /// Close the backend completely.
+ virtual int close (void);
+
+ /// This is called when we want to log a message.
+ virtual int log (ACE_Log_Record &log_record);
+
+private:
+ HANDLE evlog_handle_;
+};
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_NT_EVENT_LOG_H */
diff --git a/ace/Logging/Log_Msg_UNIX_Syslog.cpp b/ace/Logging/Log_Msg_UNIX_Syslog.cpp
new file mode 100644
index 00000000000..3389849240b
--- /dev/null
+++ b/ace/Logging/Log_Msg_UNIX_Syslog.cpp
@@ -0,0 +1,186 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG)
+
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_UNIX_Syslog.h"
+#include "ace/Log_Record.h"
+
+// NOTE:
+// The ACE_Log_Msg_UNIX_Syslog class can use the openlog(),
+// setlogmask(), syslog() and closelog() routines in a thread safe
+// manner (versus using openlog_r(), et. al.), as the ACE_Log_Msg
+// class uses the lock provided by its local ACE_Log_Msg_Manager
+// class when calling the methods of the backend classes. As a
+// result, logging semantics with respect to the UNIX syslog
+// facility, will be the same for all threads in a process. This
+// should not be too limiting, as the ACE_Log_Msg class itself can
+// be used to control thread specific logging behavior.
+
+ACE_Log_Msg_UNIX_Syslog::ACE_Log_Msg_UNIX_Syslog (void)
+{
+}
+
+ACE_Log_Msg_UNIX_Syslog::~ACE_Log_Msg_UNIX_Syslog (void)
+{
+ (void) this->close ();
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::open (const ACE_TCHAR * logger_key)
+{
+ if (logger_key == 0)
+ logger_key = ACE_Log_Msg::program_name ();
+
+ // Initialize the UNIX syslog facility. Default the syslog log
+ // options LOG_CONS and LOG_PID to be set. There really should be a
+ // logging strategy option to control the syslog log options,
+ // however, we'll take the easy way out for now.
+ openlog (ACE_const_cast (char *, logger_key),
+ LOG_CONS|LOG_PID,
+ ACE_DEFAULT_SYSLOG_FACILITY);
+
+ // Enable logging of all syslog priorities. If logging of all
+ // priorities is not desired, use the ACE_Log_Msg::priority_mask()
+ // method to control the log output sent to the syslog daemon via
+ // the log() method, or use the system's syslog.conf file to select
+ // desired level of information.
+
+#if !defined (ACE_LACKS_SETLOGMASK)
+ (void) setlogmask (LOG_UPTO (LOG_DEBUG));
+#endif /* ACE_LACKS_SETLOGMASK */
+
+ return 0;
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::reset (void)
+{
+ return this->close ();
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::close (void)
+{
+ closelog();
+ return 0;
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::log (ACE_Log_Record &log_record)
+{
+ int syslog_priority = this->convert_log_priority (log_record.type ());
+ int flags = ACE_LOG_MSG->flags ();
+
+ // The UNIX syslog() facility does not support multi-line messages.
+ // Break up the message data into separate lines and send each line
+ // to the syslog daemon.
+
+ ACE_TCHAR message[ACE_Log_Record::MAXVERBOSELOGMSGLEN];
+ ACE_OS::strcpy (message, log_record.msg_data ());
+
+ for (ACE_TCHAR *line = ACE_OS::strtok (message, ACE_LIB_TEXT ("\n"));
+ line != 0;
+ line = ACE_OS::strtok (0, ACE_LIB_TEXT ("\n")))
+ {
+ // Format the message line. Note that the processing for
+ // VERBOSE is the same as for VERBOSE_LITE, since syslog()
+ // already provides us with the hostname and PID. However, the
+ // timestamp is duplicated (albeit a shortened version) to
+ // provide a timestamp with greater precision than that provided
+ // by syslog().
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::VERBOSE)
+ || ACE_BIT_ENABLED (flags, ACE_Log_Msg::VERBOSE_LITE))
+ {
+ ACE_TCHAR date_and_time[35];
+ syslog (syslog_priority,
+ ACE_LIB_TEXT ("%s: %s: %s"),
+ ACE::timestamp (date_and_time, sizeof (date_and_time), 1),
+ ACE_Log_Record::priority_name (ACE_Log_Priority(log_record.type ())),
+ line);
+ }
+ else // No formatting required.
+ syslog (syslog_priority, ACE_LIB_TEXT ("%s"), line);
+ }
+
+ return 0;
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::convert_log_priority (int lm_priority)
+{
+ int syslog_priority;
+ switch (lm_priority)
+ {
+ case LM_TRACE:
+ case LM_DEBUG:
+ syslog_priority = LOG_DEBUG;
+ break;
+ case LM_STARTUP:
+ case LM_SHUTDOWN:
+ case LM_INFO:
+ syslog_priority = LOG_INFO;
+ break;
+ case LM_NOTICE:
+ syslog_priority = LOG_NOTICE;
+ break;
+ case LM_WARNING:
+ syslog_priority = LOG_WARNING;
+ break;
+ case LM_CRITICAL:
+ syslog_priority = LOG_CRIT;
+ break;
+ case LM_ALERT:
+ syslog_priority = LOG_ALERT;
+ break;
+ case LM_EMERGENCY:
+ syslog_priority = LOG_EMERG;
+ break;
+ case LM_ERROR:
+ default:
+ syslog_priority = LOG_ERR;
+ break;
+ }
+
+ return syslog_priority;
+}
+
+int
+ACE_Log_Msg_UNIX_Syslog::convert_log_mask (int lm_mask)
+{
+ int syslog_mask = 0;
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_TRACE)
+ || ACE_BIT_ENABLED (lm_mask, LM_DEBUG))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_DEBUG));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_STARTUP)
+ || ACE_BIT_ENABLED (lm_mask, LM_SHUTDOWN)
+ || ACE_BIT_ENABLED (lm_mask, LM_INFO))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_INFO));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_NOTICE))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_NOTICE));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_ERROR))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_ERR));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_WARNING))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_WARNING));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_CRITICAL))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_CRIT));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_ALERT))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_ALERT));
+
+ if (ACE_BIT_ENABLED (lm_mask, LM_EMERGENCY))
+ ACE_SET_BITS (syslog_mask, LOG_MASK(LOG_EMERG));
+
+ return syslog_mask;
+}
+
+#endif /* !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG) */
diff --git a/ace/Logging/Log_Msg_UNIX_Syslog.h b/ace/Logging/Log_Msg_UNIX_Syslog.h
new file mode 100644
index 00000000000..4c63d9de80e
--- /dev/null
+++ b/ace/Logging/Log_Msg_UNIX_Syslog.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Log_Msg_UNIX_Syslog.h
+ *
+ * $Id$
+ *
+ * @author Jerry D. De Master <jdemaster@rite-solutions.com>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_MSG_UNIX_SYSLOG_H
+#define ACE_LOG_MSG_UNIX_SYSLOG_H
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG)
+
+#include "ace/Log_Msg_Backend.h"
+
+/**
+ * @class ACE_Log_Msg_UNIX_Syslog
+ *
+ * @brief Implements an ACE_Log_Msg_Backend that logs messages to a UNIX
+ * system's syslog facility.
+ */
+class ACE_Export ACE_Log_Msg_UNIX_Syslog : public ACE_Log_Msg_Backend
+{
+public:
+ /// Constructor
+ ACE_Log_Msg_UNIX_Syslog (void);
+
+ /// Destructor
+ virtual ~ACE_Log_Msg_UNIX_Syslog (void);
+
+ /// Open a new event log.
+ /**
+ * Initialize the event logging facility.
+ * @param logger_key The name of the calling program. This name is
+ * used as the @arg ident in the syslog entries. If
+ * it is 0 (no name), the application name as
+ * returned from ACE_Log_Msg::program_name() is used.
+ */
+ virtual int open (const ACE_TCHAR *logger_key);
+
+ /// Reset the backend.
+ virtual int reset (void);
+
+ /// Close the backend completely.
+ virtual int close (void);
+
+ /// This is called when we want to log a message.
+ virtual int log (ACE_Log_Record &log_record);
+
+private:
+ /// Convert an ACE_Log_Priority value to the corresponding syslog priority.
+ int convert_log_priority (int lm_priority);
+
+ /// Convert an ACE_Log_Priority mask to the corresponding syslog mask value.
+ int convert_log_mask (int lm_mask);
+};
+
+#endif /* !ACE_WIN32 && !ACE_HAS_WINCE */
+
+#include "ace/post.h"
+#endif /* ACE_LOG_MSG_UNIX_SYSLOG_H */
diff --git a/ace/Logging/Log_Priority.h b/ace/Logging/Log_Priority.h
new file mode 100644
index 00000000000..52c68acb918
--- /dev/null
+++ b/ace/Logging/Log_Priority.h
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Log_Priority.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOG_PRIORITY_H
+#define ACE_LOG_PRIORITY_H
+#include "ace/pre.h"
+
+/**
+ * @brief This data type indicates the relative priorities of the
+ * logging messages, from lowest to highest priority.
+ *
+ * These values are defined using powers of two so that it's
+ * possible to form a mask to turn them on or off dynamically.
+ * We only use 12 bits, however, so users are free to use the
+ * remaining 19 bits to define their own priority masks.
+ */
+enum ACE_Log_Priority
+{
+ // = Note, this first argument *must* start at 1!
+
+ /// Shutdown the logger (decimal 1).
+ LM_SHUTDOWN = 01,
+
+ /// Messages indicating function-calling sequence (decimal 2).
+ LM_TRACE = 02,
+
+ /// Messages that contain information normally of use only when
+ /// debugging a program (decimal 4).
+ LM_DEBUG = 04,
+
+ /// Informational messages (decimal 8).
+ LM_INFO = 010,
+
+ /// Conditions that are not error conditions, but that may require
+ /// special handling (decimal 16).
+ LM_NOTICE = 020,
+
+ /// Warning messages (decimal 32).
+ LM_WARNING = 040,
+
+ /// Initialize the logger (decimal 64).
+ LM_STARTUP = 0100,
+
+ /// Error messages (decimal 128).
+ LM_ERROR = 0200,
+
+ /// Critical conditions, such as hard device errors (decimal 256).
+ LM_CRITICAL = 0400,
+
+ /// A condition that should be corrected immediately, such as a
+ /// corrupted system database (decimal 512).
+ LM_ALERT = 01000,
+
+ /// A panic condition. This is normally broadcast to all users
+ /// (decimal 1024).
+ LM_EMERGENCY = 02000,
+
+ /// The maximum logging priority.
+ LM_MAX = LM_EMERGENCY,
+
+ /// Do not use!! This enum value ensures that the underlying
+ /// integral type for this enum is at least 32 bits.
+ LM_ENSURE_32_BITS = 0x7FFFFFFF
+};
+
+#include "ace/post.h"
+#endif /* ACE_LOG_PRIORITY_H */
diff --git a/ace/Logging/Log_Record.cpp b/ace/Logging/Log_Record.cpp
new file mode 100644
index 00000000000..caf0a9b4cde
--- /dev/null
+++ b/ace/Logging/Log_Record.cpp
@@ -0,0 +1,299 @@
+// $Id$
+
+#include "ace/Log_Record.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+# include "ace/Log_Record.i"
+#endif
+
+ACE_RCSID(ace, Log_Record, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Log_Record)
+
+const ACE_TCHAR *ACE_Log_Record::priority_names_[] =
+{
+ ACE_LIB_TEXT ("<none>"),
+ ACE_LIB_TEXT ("LM_SHUTDOWN"),
+ ACE_LIB_TEXT ("LM_TRACE"),
+ ACE_LIB_TEXT ("LM_DEBUG"),
+ ACE_LIB_TEXT ("LM_INFO"),
+ ACE_LIB_TEXT ("LM_NOTICE"),
+ ACE_LIB_TEXT ("LM_WARNING"),
+ ACE_LIB_TEXT ("LM_STARTUP"),
+ ACE_LIB_TEXT ("LM_ERROR"),
+ ACE_LIB_TEXT ("LM_CRITICAL"),
+ ACE_LIB_TEXT ("LM_ALERT"),
+ ACE_LIB_TEXT ("LM_EMERGENCY"),
+ ACE_LIB_TEXT ("LM_UNK(04000)"),
+ ACE_LIB_TEXT ("LM_UNK(010000)"),
+ ACE_LIB_TEXT ("LM_UNK(020000)"),
+ ACE_LIB_TEXT ("LM_UNK(040000)"),
+ ACE_LIB_TEXT ("LM_UNK(0100000)"),
+ ACE_LIB_TEXT ("LM_UNK(0200000)"),
+ ACE_LIB_TEXT ("LM_UNK(0400000)"),
+ ACE_LIB_TEXT ("LM_UNK(01000000)"),
+ ACE_LIB_TEXT ("LM_UNK(02000000)"),
+ ACE_LIB_TEXT ("LM_UNK(04000000)"),
+ ACE_LIB_TEXT ("LM_UNK(010000000)"),
+ ACE_LIB_TEXT ("LM_UNK(020000000)"),
+ ACE_LIB_TEXT ("LM_UNK(040000000)"),
+ ACE_LIB_TEXT ("LM_UNK(0100000000)"),
+ ACE_LIB_TEXT ("LM_UNK(0200000000)"),
+ ACE_LIB_TEXT ("LM_UNK(0400000000)"),
+ ACE_LIB_TEXT ("LM_UNK(01000000000)"),
+ ACE_LIB_TEXT ("LM_UNK(02000000000)"),
+ ACE_LIB_TEXT ("LM_UNK(04000000000)"),
+ ACE_LIB_TEXT ("LM_UNK(010000000000)"),
+ ACE_LIB_TEXT ("LM_UNK(020000000000)")
+};
+
+const ACE_TCHAR *
+ACE_Log_Record::priority_name (ACE_Log_Priority p)
+{
+ return ACE_Log_Record::priority_names_[ACE::log2 (p)];
+}
+
+void
+ACE_Log_Record::priority_name (ACE_Log_Priority p,
+ const ACE_TCHAR *name)
+{
+ // Name must be a statically allocated string
+ ACE_Log_Record::priority_names_[ACE::log2 (p)] = name;
+}
+
+u_long
+ACE_Log_Record::priority (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::priority");
+
+ // Get the priority of the <Log_Record> <type_>. This is computed
+ // as the base 2 logarithm of <type_> (which must be a power of 2,
+ // as defined by the enums in <ACE_Log_Priority>).
+ return ACE::log2 ((u_long) this->type_);
+}
+
+void
+ACE_Log_Record::priority (u_long p)
+{
+ ACE_TRACE ("ACE_Log_Record::priority");
+
+ // Set the priority of the <Log_Record> <type_> (which must be a
+ // power of 2, as defined by the enums in <ACE_Log_Priority>).
+ this->type_ = (ACE_UINT32) p;
+}
+
+void
+ACE_Log_Record::dump (void) const
+{
+ // ACE_TRACE ("ACE_Log_Record::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("length_ = %d\n"), this->length_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntype_ = %u\n"), this->type_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntime_stamp_ = (%d, %d)\n"), this->secs_, this->usecs_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npid_ = %u\n"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_data_ = %s\n"), this->msg_data_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_Log_Record::msg_data (const ACE_TCHAR *data)
+{
+ // ACE_TRACE ("ACE_Log_Record::msg_data");
+ ACE_OS::strsncpy (this->msg_data_, data,
+ (sizeof this->msg_data_ / sizeof (ACE_TCHAR)));
+ this->round_up ();
+}
+
+ACE_Log_Record::ACE_Log_Record (ACE_Log_Priority lp,
+ long ts_sec,
+ long p)
+ : length_ (0),
+ type_ (ACE_UINT32 (lp)),
+ secs_ (ts_sec),
+ usecs_ (0),
+ pid_ (ACE_UINT32 (p))
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+}
+
+ACE_Log_Record::ACE_Log_Record (ACE_Log_Priority lp,
+ const ACE_Time_Value &ts,
+ long p)
+ : length_ (0),
+ type_ (ACE_UINT32 (lp)),
+ secs_ ((ACE_UINT32) ts.sec ()),
+ usecs_ ((ACE_UINT32) ts.usec ()),
+ pid_ (ACE_UINT32 (p))
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+}
+
+void
+ACE_Log_Record::round_up (void)
+{
+ // ACE_TRACE ("ACE_Log_Record::round_up");
+ // Determine the length of the payload.
+ int len = (sizeof (*this) - sizeof (this->msg_data_))
+ + (sizeof (ACE_TCHAR) * ((ACE_OS::strlen (this->msg_data_) + 1)));
+
+ // Round up to the alignment.
+ this->length_ = ((len + ACE_Log_Record::ALIGN_WORDB - 1)
+ & ~(ACE_Log_Record::ALIGN_WORDB - 1));
+}
+
+ACE_Log_Record::ACE_Log_Record (void)
+ : length_ (0),
+ type_ (0),
+ secs_ (0),
+ usecs_ (0),
+ pid_ (0)
+{
+ // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record");
+}
+
+int
+ACE_Log_Record::format_msg (const ACE_TCHAR *host_name,
+ u_long verbose_flag,
+ ACE_TCHAR *verbose_msg)
+{
+ /* 0123456789012345678901234 */
+ /* Oct 18 14:25:36.000 1989<nul> */
+ ACE_TCHAR timestamp[26]; // Only used by VERBOSE and VERBOSE_LITE.
+
+ if (ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE)
+ || ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE_LITE))
+ {
+ time_t now = this->secs_;
+ ACE_TCHAR ctp[26]; // 26 is a magic number...
+
+ if (ACE_OS::ctime_r (&now, ctp, sizeof ctp) == 0)
+ return -1;
+
+ /* 01234567890123456789012345 */
+ /* Wed Oct 18 14:25:36 1989n0 */
+
+ ctp[19] = '\0'; // NUL-terminate after the time.
+ ctp[24] = '\0'; // NUL-terminate after the date.
+
+ ACE_OS::sprintf (timestamp,
+ ACE_LIB_TEXT ("%s.%03ld %s"),
+ ctp + 4,
+ ((long) this->usecs_) / 1000,
+ ctp + 20);
+ }
+
+ if (ACE_BIT_ENABLED (verbose_flag,
+ ACE_Log_Msg::VERBOSE))
+ {
+# if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS)
+ const ACE_TCHAR *lhost_name = (const ACE_TCHAR *) ((host_name == 0)
+ ? ((char *) ACE_LIB_TEXT ("<local_host>"))
+ : ((char *) host_name));
+# else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+ const ACE_TCHAR *lhost_name = ((host_name == 0)
+ ? ACE_LIB_TEXT ("<local_host>")
+ : host_name);
+# endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */
+ ACE_OS::sprintf (verbose_msg,
+ ACE_LIB_TEXT ("%s@%s@%u@%s@%s"),
+ timestamp,
+ lhost_name,
+ this->pid_,
+ ACE_Log_Record::priority_name (ACE_Log_Priority (this->type_)),
+ this->msg_data_);
+ }
+ else if (ACE_BIT_ENABLED (verbose_flag, ACE_Log_Msg::VERBOSE_LITE))
+ ACE_OS::sprintf (verbose_msg,
+ ACE_LIB_TEXT ("%s@%s@%s"),
+ timestamp,
+ ACE_Log_Record::priority_name (ACE_Log_Priority (this->type_)),
+ this->msg_data_);
+ else
+ ACE_OS::sprintf (verbose_msg,
+ ACE_LIB_TEXT ("%s"),
+ this->msg_data_);
+ return 0;
+}
+
+#if defined (ACE_HAS_WINCE)
+
+int
+ACE_Log_Record::print (const ACE_TCHAR *host_name,
+ u_long verbose_flag,
+ ACE_CE_Bridge *log_window)
+{
+ ACE_TCHAR verbose_msg [MAXVERBOSELOGMSGLEN];
+ int result = this->format_msg (host_name, verbose_flag, verbose_msg);
+
+ if (result == 0)
+ {
+ if (log_window == 0)
+ log_window = ACE_CE_Bridge::get_default_winbridge ();
+
+ // <verbose_cstring> will be deleted by <write_msg> function
+ log_window->write_msg (verbose_msg);
+ }
+
+ return result;
+}
+
+#endif /* defined (ACE_HAS_WINCE) */
+
+int
+ACE_Log_Record::print (const ACE_TCHAR *host_name,
+ u_long verbose_flag,
+ FILE *fp)
+{
+ ACE_TCHAR verbose_msg [MAXVERBOSELOGMSGLEN];
+ int result = this->format_msg (host_name,
+ verbose_flag,
+ verbose_msg);
+
+ if (result == 0)
+ {
+ if (fp != NULL)
+ {
+ int verbose_msg_len = ACE_OS::strlen (verbose_msg);
+ int fwrite_result = ACE_OS::fprintf (fp, ACE_LIB_TEXT ("%s"), verbose_msg);
+
+ // We should have written everything
+ if (fwrite_result != verbose_msg_len)
+ result = -1;
+ else
+ ACE_OS::fflush (fp);
+ }
+ }
+
+ return result;
+}
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+
+int
+ACE_Log_Record::print (const ACE_TCHAR *host_name,
+ u_long verbose_flag,
+ ostream &s)
+{
+ ACE_TCHAR verbose_msg [MAXVERBOSELOGMSGLEN];
+ int result = this->format_msg (host_name, verbose_flag, verbose_msg);
+
+ if (result == 0)
+ {
+ // Since ostream expects only chars, we cannot pass wchar_t's
+ s << ACE_TEXT_ALWAYS_CHAR (verbose_msg);
+ s.flush ();
+ }
+
+ return result;
+}
+
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
diff --git a/ace/Logging/Log_Record.h b/ace/Logging/Log_Record.h
new file mode 100644
index 00000000000..ac7ec80743e
--- /dev/null
+++ b/ace/Logging/Log_Record.h
@@ -0,0 +1,202 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Log_Record.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+// These need to go outside of the #ifdef to avoid problems with
+// circular dependencies...
+#include "ace/OS/OS.h"
+
+#include "ace/Logging/Log_Priority.h"
+
+#ifndef ACE_LOG_RECORD_H
+#define ACE_LOG_RECORD_H
+#include "ace/pre.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/// Defines the structure of an ACE logging record.
+class ACE_Export ACE_Log_Record
+{
+public:
+ enum
+ {
+ /// Maximum size of a logging message.
+ MAXLOGMSGLEN = ACE_MAXLOGMSGLEN,
+
+ /// Most restrictive alignment.
+ ALIGN_WORDB = 8,
+
+ /// Size used by verbose mode.
+ /// 20 (date) + 15 (host_name) + 10 (pid) + 10 (type)
+ /// + 4 (@) ... + ? (progname)
+ VERBOSE_LEN = 128,
+
+ /// Maximum size of a logging message with the verbose headers
+ MAXVERBOSELOGMSGLEN = VERBOSE_LEN + MAXLOGMSGLEN
+ };
+
+ // = Initialization
+ /**
+ * Create a <Log_Record> and set its priority, time stamp, and
+ * process id.
+ * Create a <Log_Record> and set its priority, time stamp, and
+ * process id.
+ */
+ ACE_Log_Record (void);
+ ACE_Log_Record (ACE_Log_Priority lp,
+ long time_stamp,
+ long pid);
+ ACE_Log_Record (ACE_Log_Priority lp,
+ const ACE_Time_Value &time_stamp,
+ long pid);
+
+ /// Default dtor.
+ ~ACE_Log_Record (void);
+
+
+ /// Write the contents of the logging record to the appropriate
+ /// <FILE>.
+ int print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+#if !defined (ACE_HAS_WINCE)
+ FILE *fp = stderr);
+#else
+ FILE *fp);
+#endif /* ACE_HAS_WINCE */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ /// Write the contents of the logging record to the appropriate
+ /// <ostream>.
+ int print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ostream &stream);
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+ int format_msg (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ACE_TCHAR *verbose_msg);
+
+#if defined (ACE_HAS_WINCE)
+ /// For Windows CE, the default is to log messages to a preset
+ /// window.
+ int print (const ACE_TCHAR host_name[],
+ u_long verbose_flag,
+ ACE_CE_Bridge *log_ = 0);
+#endif /* defined (ACE_HAS_WINCE) */
+
+ /**
+ * Returns a character array with the string form of the
+ * <ACE_Log_Priority> parameter. This is used for the verbose
+ * printing format.
+ */
+ static const ACE_TCHAR *priority_name (ACE_Log_Priority p);
+
+ // IMPORTANT: <name> must be a statically allocated const ACE_TCHAR*
+ static void priority_name (ACE_Log_Priority p,
+ const ACE_TCHAR *name);
+
+ // = Marshall/demarshall
+ /// Encode the <Log_Record> for transmission on the network.
+ void encode (void);
+
+ /// Decode the <Log_Record> received from the network.
+ void decode (void);
+
+ // = Set/get methods
+
+ /// Get the type of the <Log_Record>.
+ long type (void) const;
+
+ /// Set the type of the <Log_Record>.
+ void type (long);
+
+ /**
+ * Get the priority of the <Log_Record> <type_>. This is computed
+ * as the base 2 logarithm of <type_> (which must be a power of 2,
+ * as defined by the enums in <ACE_Log_Priority>).
+ */
+ u_long priority (void) const;
+
+ /// Set the priority of the <Log_Record> <type_> (which must be a
+ /// power of 2, as defined by the enums in <ACE_Log_Priority>).
+ void priority (u_long num);
+
+ /// Get the length of the <Log_Record>.
+ long length (void) const;
+
+ /// Set the length of the <Log_Record>.
+ void length (long);
+
+ /// Get the time stamp of the <Log_Record>.
+ ACE_Time_Value time_stamp (void) const;
+
+ /// Set the time stamp of the <Log_Record>.
+ void time_stamp (const ACE_Time_Value &);
+
+ /// Get the process id of the <Log_Record>.
+ long pid (void) const;
+
+ /// Set the process id of the <Log_Record>.
+ void pid (long);
+
+ /// Get the message data of the <Log_Record>.
+ const ACE_TCHAR *msg_data (void) const;
+
+ /// Set the message data of the <Log_Record>.
+ void msg_data (const ACE_TCHAR *data);
+
+ /// Get the size of the message data of the <Log_Record>, including
+ /// a byte for the NUL.
+ size_t msg_data_len (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Round up to the alignment restrictions.
+ void round_up (void);
+
+ /**
+ * Total length of the logging record in bytes. This field *must*
+ * come first in order for various IPC framing mechanisms to work
+ * correctly. In addition, the field must be an ACE_INT32 in order
+ * to be passed portably across platforms.
+ */
+ ACE_INT32 length_;
+
+ /// Type of logging record.
+ ACE_UINT32 type_;
+
+ /// Time that the logging record was generated.
+ ACE_UINT32 secs_;
+ ACE_UINT32 usecs_;
+
+ /// Id of process that generated the logging record.
+ ACE_UINT32 pid_;
+
+ /// Logging record data
+ ACE_TCHAR msg_data_[MAXLOGMSGLEN + 1]; // Add one for NUL-terminator.
+
+ /// Symbolic names for the <ACE_Log_Priority> enums.
+ static const ACE_TCHAR *priority_names_[];
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "Log_Record.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_LOG_RECORD_H */
diff --git a/ace/Logging/Log_Record.i b/ace/Logging/Log_Record.i
new file mode 100644
index 00000000000..a5ecf5c62bf
--- /dev/null
+++ b/ace/Logging/Log_Record.i
@@ -0,0 +1,107 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Log_Record.i
+
+ASYS_INLINE
+ACE_Log_Record::~ACE_Log_Record (void)
+{
+}
+
+ASYS_INLINE void
+ACE_Log_Record::encode (void)
+{
+ ACE_TRACE ("ACE_Log_Record::encode");
+ this->length_ = htonl (this->length_);
+ this->type_ = htonl (this->type_);
+ // Make sure we don't enclose the sec() and usec() fields until
+ // they've been normalized.
+ this->secs_ = htonl (this->secs_);
+ this->usecs_ = htonl (this->usecs_);
+ this->pid_ = htonl (this->pid_);
+}
+
+ASYS_INLINE void
+ACE_Log_Record::decode (void)
+{
+ ACE_TRACE ("ACE_Log_Record::decode");
+ ACE_Time_Value tv (ntohl (this->secs_),
+ ntohl (this->usecs_));
+
+ this->secs_ = tv.sec ();
+ this->usecs_ = tv.usec ();
+ this->type_ = ntohl (this->type_);
+ this->pid_ = ntohl (this->pid_);
+ this->length_ = ntohl (this->length_);
+}
+
+ASYS_INLINE long
+ACE_Log_Record::type (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::type");
+ return (long) this->type_;
+}
+
+ASYS_INLINE void
+ACE_Log_Record::type (long t)
+{
+ ACE_TRACE ("ACE_Log_Record::type");
+ this->type_ = (ACE_UINT32) t;
+}
+
+ASYS_INLINE long
+ACE_Log_Record::length (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::length");
+ return (long) this->length_;
+}
+
+ASYS_INLINE void
+ACE_Log_Record::length (long l)
+{
+ ACE_TRACE ("ACE_Log_Record::length");
+ this->length_ = ACE_static_cast (ACE_UINT32, l);
+}
+
+ASYS_INLINE ACE_Time_Value
+ACE_Log_Record::time_stamp (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::time_stamp");
+ return ACE_Time_Value ((long) this->secs_, (long) this->usecs_);
+}
+
+ASYS_INLINE void
+ACE_Log_Record::time_stamp (const ACE_Time_Value &ts)
+{
+ ACE_TRACE ("ACE_Log_Record::time_stamp");
+ this->secs_ = (ACE_UINT32) ts.sec ();
+ this->usecs_ = (ACE_UINT32) ts.usec ();
+}
+
+ASYS_INLINE long
+ACE_Log_Record::pid (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::pid");
+ return (long) this->pid_;
+}
+
+ASYS_INLINE void
+ACE_Log_Record::pid (long p)
+{
+ ACE_TRACE ("ACE_Log_Record::pid");
+ this->pid_ = (ACE_UINT32) p;
+}
+
+ASYS_INLINE const ACE_TCHAR *
+ACE_Log_Record::msg_data (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::msg_data");
+ return this->msg_data_;
+}
+
+ASYS_INLINE size_t
+ACE_Log_Record::msg_data_len (void) const
+{
+ ACE_TRACE ("ACE_Log_Record::msg_data_len");
+ return ACE_OS::strlen (this->msg_data_) + 1;
+}
diff --git a/ace/Logging/Logging_Strategy.cpp b/ace/Logging/Logging_Strategy.cpp
new file mode 100644
index 00000000000..5352fc742fc
--- /dev/null
+++ b/ace/Logging/Logging_Strategy.cpp
@@ -0,0 +1,495 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/streams.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Logging_Strategy.h"
+
+ACE_RCSID(lib, Logging_Strategy, "$Id$")
+
+// Parse the string containing (thread) priorities and set them
+// accordingly.
+
+void
+ACE_Logging_Strategy::priorities (ACE_TCHAR *priority_string,
+ ACE_Log_Msg::MASK_TYPE mask)
+{
+ u_long priority_mask = 0;
+
+ // Choose priority mask to change.
+
+ if (mask == ACE_Log_Msg::PROCESS)
+ priority_mask = process_priority_mask_;
+ else
+ priority_mask = thread_priority_mask_;
+
+ // Parse string and alternate priority mask.
+
+ for (ACE_TCHAR *priority = ACE_OS::strtok (priority_string,
+ ACE_LIB_TEXT ("|"));
+ priority != 0;
+ priority = ACE_OS::strtok (0, ACE_LIB_TEXT ("|")))
+ {
+ if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("TRACE")) == 0)
+ ACE_SET_BITS (priority_mask, LM_TRACE);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~TRACE")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_TRACE);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("DEBUG")) == 0)
+ ACE_SET_BITS (priority_mask, LM_DEBUG);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~DEBUG")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_DEBUG);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("INFO")) == 0)
+ ACE_SET_BITS (priority_mask, LM_INFO);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~INFO")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_INFO);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("NOTICE")) == 0)
+ ACE_SET_BITS (priority_mask, LM_NOTICE);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~NOTICE")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_NOTICE);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("WARNING")) == 0)
+ ACE_SET_BITS (priority_mask, LM_WARNING);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~WARNING")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_WARNING);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("ERROR")) == 0)
+ ACE_SET_BITS (priority_mask, LM_ERROR);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~ERROR")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_ERROR);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("CRITICAL")) == 0)
+ ACE_SET_BITS (priority_mask, LM_CRITICAL);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~CRITICAL")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_CRITICAL);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("ALERT")) == 0)
+ ACE_SET_BITS (priority_mask, LM_ALERT);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~ALERT")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_ALERT);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("EMERGENCY")) == 0)
+ ACE_SET_BITS (priority_mask, LM_EMERGENCY);
+ else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~EMERGENCY")) == 0)
+ ACE_CLR_BITS (priority_mask, LM_EMERGENCY);
+ }
+
+ // Affect right priority mask.
+
+ if (mask == ACE_Log_Msg::PROCESS)
+ process_priority_mask_ = priority_mask;
+ else
+ thread_priority_mask_ = priority_mask;
+}
+
+// Parse the string containing all the flags and set the flags
+// accordingly.
+
+void
+ACE_Logging_Strategy::tokenize (ACE_TCHAR *flag_string)
+{
+ for (ACE_TCHAR *flag = ACE_OS::strtok (flag_string,
+ ACE_LIB_TEXT ("|"));
+ flag != 0;
+ flag = ACE_OS::strtok (0, ACE_LIB_TEXT ("|")))
+ {
+ if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("STDERR")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::STDERR);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("LOGGER")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::LOGGER);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("OSTREAM")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::OSTREAM);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("VERBOSE")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("VERBOSE_LITE")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE_LITE);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("SILENT")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::SILENT);
+ else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("SYSLOG")) == 0)
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::SYSLOG);
+ }
+}
+
+int
+ACE_Logging_Strategy::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Logging_Strategy::parse_args");
+ ACE_TCHAR *temp;
+
+ // Perform data member initializations. BTW, do *not* initialize
+ // <thread_priority_mask_> or <process_priority_mask_> here to avoid
+ // unduing the behavior in <init>, where these are set by
+ // <ACE_Log_Msg::instance>.
+ this->flags_ = 0;
+ this->wipeout_logfile_ = 0;
+ this->count_ = 0;
+ this->fixed_number_ = 0;
+ this->order_files_ = 0;
+ this->max_file_number_ = 1;
+ this->interval_ = ACE_DEFAULT_LOGFILE_POLL_INTERVAL;
+ this->max_size_ = 0;
+
+ ACE_Get_Opt get_opt (argc, argv,
+ ACE_LIB_TEXT ("f:i:k:m:n:N:op:s:t:w"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ {
+ switch (c)
+ {
+ case 'f':
+ temp = get_opt.opt_arg ();
+ // Now tokenize the string to get all the flags
+ this->tokenize (temp);
+ // If LOGGER was specified, set up the default logger key.
+ // The key can be changed by the -k option also, so if it's
+ // been set already, don't set it.
+ if (ACE_BIT_ENABLED (this->flags_, ACE_Log_Msg::LOGGER) &&
+ this->logger_key_ == 0)
+ this->logger_key_ = ACE::strnew (ACE_DEFAULT_LOGGER_KEY);
+ break;
+ case 'i':
+ // Interval (in secs) at which logfile size is sampled.
+ this->interval_ = ACE_OS::strtoul (get_opt.opt_arg (), 0, 10);
+ break;
+ case 'k':
+ // Ensure that the LOGGER flag is set
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::LOGGER);
+ delete [] this->logger_key_;
+ this->logger_key_ = ACE::strnew (get_opt.opt_arg ());
+ break;
+ case 'm':
+ // Maximum logfile size (in KB). Must be a non-zero value.
+ this->max_size_ = ACE_OS::strtoul (get_opt.opt_arg (), 0, 10);
+ this->max_size_ <<= 10; // convert to KB
+ break;
+ case 'n':
+ delete [] this->program_name_;
+ this->program_name_ = ACE::strnew (get_opt.opt_arg ());
+ break;
+ case 'N':
+ // The max number for the log_file being created
+ this->max_file_number_ = ACE_OS::atoi (get_opt.opt_arg ()) - 1;
+ this->fixed_number_ = 1;
+ break;
+ case 'o':
+ // Log_files generation order
+ this->order_files_ = 1;
+ break;
+ case 'p':
+ temp = get_opt.opt_arg ();
+ // Now tokenize the string to setup process log priority
+ this->priorities (temp, ACE_Log_Msg::PROCESS);
+ break;
+ case 's':
+ // Ensure that the OSTREAM flag is set
+ ACE_SET_BITS (this->flags_, ACE_Log_Msg::OSTREAM);
+ delete [] this->filename_;
+ this->filename_ = ACE::strnew (get_opt.opt_arg ());
+ break;
+ case 't':
+ temp = get_opt.opt_arg ();
+ // Now tokenize the string to setup thread log priority
+ this->priorities (temp, ACE_Log_Msg::THREAD);
+ break;
+ case 'w':
+ // Cause the logfile to be wiped out, both on startup and on
+ // reconfigure.
+ this->wipeout_logfile_ = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+ACE_Logging_Strategy::ACE_Logging_Strategy (void)
+ : log_msg_ (ACE_Log_Msg::instance ())
+{
+#if defined (ACE_DEFAULT_LOGFILE)
+ this->filename_ = ACE::strnew (ACE_DEFAULT_LOGFILE);
+#else /* ACE_DEFAULT_LOGFILE */
+ ACE_NEW (this->filename_,
+ ACE_TCHAR[MAXPATHLEN + 1]);
+
+ // Get the temporary directory
+ if (ACE_Lib_Find::get_temp_dir
+ (this->filename_,
+ MAXPATHLEN - 7) == -1) // 7 for "logfile"
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Temporary path too long, ")
+ ACE_LIB_TEXT ("defaulting to current directory\n")));
+ this->filename_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->filename_,
+ ACE_LIB_TEXT ("logfile"));
+#endif /* ACE_DEFAULT_LOGFILE */
+ this->logger_key_ = 0;
+ this->program_name_ = 0;
+}
+
+int
+ACE_Logging_Strategy::fini (void)
+{
+ delete [] this->filename_;
+ delete [] this->logger_key_;
+ delete [] this->program_name_;
+ return 0;
+}
+
+int
+ACE_Logging_Strategy::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Logging_Strategy::init");
+
+ // Store current priority masks for changes in <parse_args>.
+
+ this->process_priority_mask_ =
+ this->log_msg_->priority_mask (ACE_Log_Msg::PROCESS);
+
+ this->thread_priority_mask_ =
+ this->log_msg_->priority_mask (ACE_Log_Msg::THREAD);
+
+ // Use the options hook to parse the command line arguments.
+ this->parse_args (argc, argv);
+
+ // Setup priorities (to original if not specified on command line)
+
+ this->log_msg_->priority_mask (thread_priority_mask_,
+ ACE_Log_Msg::THREAD);
+
+ this->log_msg_->priority_mask (process_priority_mask_,
+ ACE_Log_Msg::PROCESS);
+
+ // Check if any flags were specified. If none were specified, let
+ // the default behavior take effect.
+ if (this->flags_ != 0)
+ {
+ // Clear all flags
+ this->log_msg_->clr_flags (ACE_Log_Msg::STDERR
+ | ACE_Log_Msg::LOGGER
+ | ACE_Log_Msg::OSTREAM
+ | ACE_Log_Msg::VERBOSE
+ | ACE_Log_Msg::VERBOSE_LITE
+ | ACE_Log_Msg::SILENT
+ | ACE_Log_Msg::SYSLOG);
+ // Check if OSTREAM bit is set
+ if (ACE_BIT_ENABLED (this->flags_,
+ ACE_Log_Msg::OSTREAM))
+ {
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ FILE *output_file = 0;
+ if (wipeout_logfile_)
+ output_file = ACE_OS::fopen (this->filename_, "wt");
+ else
+ output_file = ACE_OS::fopen (this->filename_, "at");
+ if (output_file == 0)
+ return -1;
+#else
+ ofstream *output_file = 0;
+ // Create a new ofstream to direct output to the file.
+ if (wipeout_logfile_)
+ ACE_NEW_RETURN
+ (output_file,
+ ofstream (ACE_TEXT_ALWAYS_CHAR (this->filename_)),
+ -1);
+ else
+ ACE_NEW_RETURN
+ (output_file,
+ ofstream (ACE_TEXT_ALWAYS_CHAR (this->filename_),
+ ios::app | ios::out),
+ -1);
+ if (output_file->rdstate () != ios::goodbit)
+ {
+ delete output_file;
+ return -1;
+ }
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ // Set the <output_file> that'll be used by the rest of the
+ // code.
+ this->log_msg_->msg_ostream (output_file);
+
+ // Setup a timeout handler to perform the maximum file size
+ // check (if required).
+ if ((this->interval_ > 0) && (this->max_size_ > 0))
+ {
+ if (this->reactor () == 0)
+ // Use singleton.
+ this->reactor (ACE_Reactor::instance ());
+
+ this->reactor ()->schedule_timer
+ (this, 0,
+ ACE_Time_Value (this->interval_),
+ ACE_Time_Value (this->interval_));
+ }
+ }
+ // Now set the flags for Log_Msg
+ this->log_msg_->set_flags (this->flags_);
+ }
+
+ return this->log_msg_->open (this->program_name_,
+ this->log_msg_->flags (),
+ this->logger_key_);
+}
+
+int
+ACE_Logging_Strategy::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ if ((size_t) ACE_OS::fseek (this->log_msg_->msg_ostream (),
+ 0,
+ SEEK_CUR) > this->max_size_)
+#else
+ if ((size_t) this->log_msg_->msg_ostream ()->tellp ()
+ > this->max_size_)
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ {
+ // Lock out any other logging.
+ if (this->log_msg_->acquire ())
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Cannot acquire lock!\n")),
+ -1);
+
+ // Close the current ostream.
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ FILE *output_file = (FILE *) this->log_msg_->msg_ostream ();
+ ACE_OS::fclose (output_file);
+ // We'll call msg_ostream() modifier later.
+#else
+ ofstream *output_file =
+ (ofstream *) this->log_msg_->msg_ostream ();
+ output_file->close ();
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ // Save current logfile to logfile.old analyze if it was set any
+ // fixed number for the log_files.
+ if (fixed_number_)
+ {
+ if (max_file_number_ < 1) //we only want one file
+ {
+ // Just unlink the file.
+ ACE_OS::unlink (this->filename_);
+
+ // Open a new log file with the same name.
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ output_file = ACE_OS::fopen (this->filename_, "wt");
+
+ if (output_file == 0)
+ return -1;
+
+ this->log_msg_->msg_ostream (output_file);
+#else
+ output_file->open (ACE_TEXT_ALWAYS_CHAR (this->filename_),
+ ios::out);
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+
+ // Release the lock previously acquired.
+ this->log_msg_->release ();
+ return 0;
+ }
+ }
+ count_++;
+
+ // Set the number of digits of the log_files labels.
+ int digits = 1, res = count_;
+ while((res = (res / 10))>0)
+ digits++;
+
+ if (ACE_OS::strlen (this->filename_) + digits <= MAXPATHLEN)
+ {
+ ACE_TCHAR backup[MAXPATHLEN+1];
+
+ // analyse if it was chosen the mode which will order the
+ // log_files
+ if (order_files_)
+ {
+ ACE_TCHAR to_backup[MAXPATHLEN+1];
+
+ // reorder the logs starting at the oldest (the biggest
+ // number) watch if we reached max_file_number_.
+ int max_num;
+ if (fixed_number_ && count_ > max_file_number_)
+ // count_ will always be bigger than max_file_number_,
+ // so do nothing so to always reorder files from
+ // max_file_number_.
+ max_num = max_file_number_;
+ else
+ max_num = count_;
+
+ for (int i = max_num ; i > 1 ;i--)
+ {
+ ACE_OS::sprintf (backup,
+ ACE_LIB_TEXT ("%s.%d"),
+ this->filename_,
+ i);
+ ACE_OS::sprintf (to_backup,
+ ACE_LIB_TEXT ("%s.%d"),
+ this->filename_,
+ i - 1);
+
+ // Remove any existing old file; ignore error as
+ // file may not exist.
+ ACE_OS::unlink (backup);
+
+ // Rename the current log file to the name of the
+ // backup log file.
+ ACE_OS::rename (to_backup, backup);
+ }
+ ACE_OS::sprintf (backup,
+ ACE_LIB_TEXT ("%s.1"),
+ this->filename_);
+ }
+ else
+ {
+ if (fixed_number_ && count_>max_file_number_)
+ count_ = 1; // start over from 1
+
+ ACE_OS::sprintf (backup,
+ ACE_LIB_TEXT ("%s.%d"),
+ this->filename_,
+ count_);
+ }
+
+ // Remove any existing old file; ignore error as file may
+ // not exist.
+ ACE_OS::unlink (backup);
+
+ // Rename the current log file to the name of the backup log
+ // file.
+ ACE_OS::rename (this->filename_, backup);
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Backup file name too long; ")
+ ACE_LIB_TEXT ("backup logfile not saved.\n")));
+
+ // Open a new log file by the same name
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ output_file = ACE_OS::fopen (this->filename_, "wt");
+
+ if (output_file == 0)
+ return -1;
+
+ this->log_msg_->msg_ostream (output_file);
+#else
+ output_file->open (ACE_TEXT_ALWAYS_CHAR (this->filename_),
+ ios::out);
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+
+ // Release the lock previously acquired.
+ this->log_msg_->release ();
+ }
+
+ return 0;
+}
+
+void
+ACE_Logging_Strategy::log_msg (ACE_Log_Msg *log_msg)
+{
+ this->log_msg_ = log_msg;
+}
+
+// The following is a "Factory" used by the ACE_Service_Config and
+// svc.conf file to dynamically initialize the state of the
+// Logging_Strategy.
+
+ACE_FACTORY_DEFINE (ACE, ACE_Logging_Strategy)
+
diff --git a/ace/Logging/Logging_Strategy.h b/ace/Logging/Logging_Strategy.h
new file mode 100644
index 00000000000..024455ddebb
--- /dev/null
+++ b/ace/Logging/Logging_Strategy.h
@@ -0,0 +1,169 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Logging_Strategy.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOGGING_STRATEGY_H
+#define ACE_LOGGING_STRATEGY_H
+
+#include "ace/Service_Object.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_DEFAULT_LOGFILE_POLL_INTERVAL)
+#define ACE_DEFAULT_LOGFILE_POLL_INTERVAL 600 /* Seconds */
+#endif /* ACE_DEFAULT_LOGFILE_POLL_INTERVAL */
+
+/**
+ * @class ACE_Logging_Strategy
+ *
+ * @brief This class provides the hooks to control the output produced
+ * by any of the network services.
+ *
+ * Depending upon when this service is invoked and with what
+ * flags, the output of other network services can be
+ * controlled. The output can be streamed to stderr, to a file,
+ * to a logging daemon, or it can be set to be "silent".
+ * If logging records are output to a file, the file can be set
+ * to a maximum size and repeatedly split into new files. The
+ * log file size can be limited at any logging point (i.e.,
+ * application, client logging daemon, or server logging daemon)
+ * by specifying the -i <sample_interval_in_secs> and -m
+ * <max_size_in_KB> options for the Logging_Strategy class in a
+ * svc.conf file.
+ *
+ * By default, two logfiles are generated. It's possible, however, to
+ * generate as many logfiles as necessary to store all the
+ * information. To achieve this, it is only necessary to indicate the
+ * maximum size of the logfiles via the -m option and the process will
+ * generate automatically the logfiles. You can control the total
+ * number of logfiles created via the -n option.
+ *
+ * By using the -o option we can also choose the mode of organization
+ * of the files, e.g., the first one is the normal used in Unix
+ * systems (when cron rotates the logs it keeps the lowest number the
+ * most recent one), the second is for increasing speed (we only
+ * create a new log file, and don't rotate the others (fewer accesses
+ * to disk)).
+ */
+class ACE_Export ACE_Logging_Strategy : public ACE_Service_Object
+{
+public:
+ /// Constructor.
+ ACE_Logging_Strategy (void);
+
+ /// Dynamic linking initialization hook.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Dynamic linking termination hook.
+ virtual int fini (void);
+
+ /**
+ * Timeout handler which tests logfile size. If the current logfile
+ * size exceeds <max_size_>, the current logfile is closed, saved to
+ * logfile.old, and a new logfile is reopened.
+ */
+ virtual int handle_timeout (const ACE_Time_Value& tv,
+ const void* arg);
+
+ /** Parse arguments provided in svc.conf file.
+ '-f' Pass in the flags (such as OSTREAM, STDERR, LOGGER, VERBOSE,
+ SILENT, VERBOSE_LITE) used to control logging.
+ '-i' The interval (in seconds) at which the logfile size is sampled
+ (default is 0, i.e., do not sample by default).
+ '-k' Set the logging key.
+ '-m' Maximum logfile size in Kbytes.
+ '-n' Set the program name for the %n format specifier.
+ '-N' The maximum number of logfiles that we want created.
+ '-o' Specifies that we want the no standard logfiles ordering
+ (fastest processing in <handle_timeout>). Default is not to
+ order logfiles.
+ '-p' Pass in the process-wide priorities to either enable (e.g.,
+ DEBUG, INFO, WARNING, NOTICE, ERROR, CRITICAL, ALERT,
+ EMERGENCY) or to disable (e.g., ~DEBUG, ~INFO, ~WARNING,
+ ~NOTICE, ~ERROR, ~CRITICAL, ~ALERT, ~EMERGENCY).
+ '-s' Ensure that the OSTREAM flag is set
+ '-t' Pass in the thread-wide priorities to either enable (e.g.,
+ DEBUG, INFO, WARNING, NOTICE, ERROR, CRITICAL, ALERT,
+ EMERGENCY) or to disable (e.g., ~DEBUG, ~INFO, ~WARNING,
+ ~NOTICE, ~ERROR, ~CRITICAL, ~ALERT, ~EMERGENCY).
+ '-w' Cause the logfile to be wiped out, both on startup and on
+ reconfiguration.
+ */
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+
+ void log_msg (ACE_Log_Msg *log_msg);
+
+private:
+ /// Tokenize to set all the flags
+ void tokenize (ACE_TCHAR *flag_string);
+
+ /// Tokenize to set priorities (either process or thread one).
+ void priorities (ACE_TCHAR *priority_string,
+ ACE_Log_Msg::MASK_TYPE mask);
+
+ /// Current thread's priority mask set by <priorities>
+ u_long thread_priority_mask_;
+
+ /// Process-wide priority mask set by <priorities>
+ u_long process_priority_mask_;
+
+ /// Flags we keep track of.
+ u_long flags_;
+
+ /// File name we're logging to.
+ ACE_TCHAR *filename_;
+
+ /// Logger key for distributed logging.
+ ACE_TCHAR *logger_key_;
+
+ /// Program name to be used for %n format specifier.
+ ACE_TCHAR *program_name_;
+
+ /// If non-0 then wipeout the logfile, otherwise append to it.
+ /// Default value is 0.
+ int wipeout_logfile_;
+
+ /// This tells us in what file we last wrote. It will be increased
+ /// to enable multiple log files
+ int count_;
+
+ /// If non-0 we have a maximum number of log files we can write.
+ /// Default value is 0, i.e., no maximum number.
+ int fixed_number_;
+
+ /// If non-0 we order the files as we rotate them. Default value
+ /// is 0, i.e., we do not rotate files by default.
+ int order_files_;
+
+ /// Tells us what is the maximum log file to write. We will write
+ /// <max_file_number_> + 1 files (includes the current log file).
+ /// Default value is 1, i.e., 2 files by default.
+ int max_file_number_;
+
+ /// If non-zero, sampling interval (in secs) at which maximum logfile
+ /// size is checked, otherwise logfile size can grow indefinitely.
+ /// Default value is 0.
+ u_long interval_;
+
+ /// Maximum logfile size (in KB). Default value is
+ /// <ACE_DEFAULT_MAX_LOGFILE_SIZE>.
+ u_long max_size_;
+
+ /// ACE_Log_Msg instance to work with
+ ACE_Log_Msg *log_msg_;
+};
+
+ACE_FACTORY_DECLARE (ACE, ACE_Logging_Strategy)
+
+#endif /* ACE_LOGGING_STRATEGY_H */
diff --git a/ace/Logging/Trace.cpp b/ace/Logging/Trace.cpp
new file mode 100644
index 00000000000..8534da3f14c
--- /dev/null
+++ b/ace/Logging/Trace.cpp
@@ -0,0 +1,126 @@
+// $Id$
+
+// We need this to get the status of ACE_NTRACE...
+
+#include "ace/config-all.h"
+
+ACE_RCSID(ace, Trace, "$Id$")
+
+// Turn off tracing for the duration of this file.
+#if defined (ACE_NTRACE)
+#undef ACE_NTRACE
+#endif /* ACE_NTRACE */
+#define ACE_NTRACE 1
+
+#include "ace/Trace.h"
+#include "ace/Log_Msg.h"
+
+// = Static initialization.
+
+// Keeps track of how far to indent per trace call.
+int ACE_Trace::nesting_indent_ = ACE_Trace::DEFAULT_INDENT;
+
+// Is tracing enabled?
+int ACE_Trace::enable_tracing_ = ACE_Trace::DEFAULT_TRACING;
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Trace)
+
+void
+ACE_Trace::dump (void) const
+{
+}
+
+// Determine whether or not tracing is enabled
+
+int
+ACE_Trace::is_tracing (void)
+{
+ return ACE_Trace::enable_tracing_;
+}
+
+// Enable the tracing facility.
+
+void
+ACE_Trace::start_tracing (void)
+{
+ ACE_Trace::enable_tracing_ = 1;
+}
+
+// Disable the tracing facility.
+
+void
+ACE_Trace::stop_tracing (void)
+{
+ ACE_Trace::enable_tracing_ = 0;
+}
+
+// Change the nesting indentation level.
+
+void
+ACE_Trace::set_nesting_indent (int indent)
+{
+ ACE_Trace::nesting_indent_ = indent;
+}
+
+// Get the nesting indentation level.
+
+int
+ACE_Trace::get_nesting_indent (void)
+{
+ return ACE_Trace::nesting_indent_;
+}
+
+// Perform the first part of the trace, which prints out the string N,
+// the LINE, and the ACE_FILE as the function is entered.
+
+ACE_Trace::ACE_Trace (const ACE_TCHAR *n,
+ int line,
+ const ACE_TCHAR *file)
+{
+#if defined (ACE_NLOGGING)
+ ACE_UNUSED_ARG (line);
+ ACE_UNUSED_ARG (file);
+#endif /* ACE_NLOGGING */
+
+ this->name_ = n;
+
+ if (ACE_Trace::enable_tracing_)
+ {
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG ((LM_TRACE,
+ ACE_LIB_TEXT ("%*s(%t) calling %s in file `%s' on line %d\n"),
+ ACE_Trace::nesting_indent_ * lm->inc (),
+ ACE_LIB_TEXT (""),
+ this->name_,
+ file,
+ line));
+ lm->trace_active (0);
+ }
+ }
+}
+
+// Perform the second part of the trace, which prints out the NAME as
+// the function is exited.
+
+ACE_Trace::~ACE_Trace (void)
+{
+ if (ACE_Trace::enable_tracing_)
+ {
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG ((LM_TRACE,
+ ACE_LIB_TEXT ("%*s(%t) leaving %s\n"),
+ ACE_Trace::nesting_indent_ * lm->dec (),
+ ACE_LIB_TEXT (""),
+ this->name_));
+ lm->trace_active (0);
+ }
+ }
+}
diff --git a/ace/Logging/Trace.h b/ace/Logging/Trace.h
new file mode 100644
index 00000000000..6ad981d60d3
--- /dev/null
+++ b/ace/Logging/Trace.h
@@ -0,0 +1,86 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Trace.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_TRACE_H
+#define ACE_TRACE_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+/**
+ * @class ACE_Trace
+ *
+ * @brief A C++ trace facility that keeps track of which methods are
+ * entered and exited.
+ *
+ * This class uses C++ constructors and destructors to automate
+ * the ACE_Trace nesting. In addition, thread-specific storage
+ * is used to enable multiple threads to work correctly.
+ */
+class ACE_Export ACE_Trace
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Perform the first part of the trace, which prints out the string
+ /// N, the LINE, and the ACE_FILE as the function is entered.
+ ACE_Trace (const ACE_TCHAR *n,
+ int line = 0,
+ const ACE_TCHAR *file = ACE_LIB_TEXT (""));
+
+ /// Perform the second part of the trace, which prints out the NAME
+ /// as the function is exited.
+ ~ACE_Trace (void);
+
+ // = Control the tracing level.
+ /// Determine if tracing is enabled (return == 1) or not (== 0)
+ static int is_tracing(void);
+
+ /// Enable the tracing facility.
+ static void start_tracing (void);
+
+ /// Disable the tracing facility.
+ static void stop_tracing (void);
+
+ /// Change the nesting indentation level.
+ static void set_nesting_indent (int indent);
+
+ /// Get the nesting indentation level.
+ static int get_nesting_indent (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+private:
+ // Keeps track of how deeply the call stack is nested (this is
+ // maintained in thread-specific storage to ensure correctness in
+ // multiple threads of control.
+
+ /// Name of the method we are in.
+ const ACE_TCHAR *name_;
+
+ /// Keeps track of how far to indent per trace call.
+ static int nesting_indent_;
+
+ /// Is tracing enabled?
+ static int enable_tracing_;
+
+ /// Default values.
+ enum
+ {
+ DEFAULT_INDENT = 3,
+ DEFAULT_TRACING = 1
+ };
+};
+
+#include "ace/post.h"
+#endif /* ACE_TRACE_H */
diff --git a/ace/Memory/Based_Pointer_Repository.cpp b/ace/Memory/Based_Pointer_Repository.cpp
new file mode 100644
index 00000000000..ba1283fb41a
--- /dev/null
+++ b/ace/Memory/Based_Pointer_Repository.cpp
@@ -0,0 +1,123 @@
+// $Id$
+
+#include "ace/Map_Manager.h"
+#include "ace/Based_Pointer_Repository.h"
+
+class ACE_Based_Pointer_Repository_Rep
+{
+ // = TITLE
+ // Implementation for the <ACE_Based_Pointer_Repository>.
+ //
+ // = DESCRIPTION
+ // Every memory pool in ACE binds it's mapping base address and
+ // the mapped size to this repository every time it maps/remaps a
+ // new chunk of memory successfully.
+
+public:
+ // Useful typedefs.
+ typedef ACE_Map_Manager <void *, size_t, ACE_Null_Mutex> MAP_MANAGER;
+ typedef ACE_Map_Iterator < void *, size_t, ACE_Null_Mutex> MAP_ITERATOR;
+ typedef ACE_Map_Entry <void *, size_t> MAP_ENTRY;
+
+ MAP_MANAGER addr_map_;
+ // Keeps track of the mapping between addresses and their associated
+ // values.
+
+ ACE_SYNCH_MUTEX lock_;
+ // Synchronize concurrent access to the map.
+};
+
+ACE_Based_Pointer_Repository::ACE_Based_Pointer_Repository (void)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Repository::ACE_Based_Pointer_Repository");
+ ACE_NEW (this->rep_,
+ ACE_Based_Pointer_Repository_Rep);
+}
+
+ACE_Based_Pointer_Repository::~ACE_Based_Pointer_Repository (void)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Repository::~ACE_Based_Pointer_Repository");
+ delete this->rep_;
+}
+
+// Search for appropriate base address in repository
+
+int
+ACE_Based_Pointer_Repository::find (void *addr,
+ void *&base_addr)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Repository::find");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->rep_->lock_, -1);
+ ACE_Based_Pointer_Repository_Rep::MAP_ENTRY *ce = 0;
+
+ for (ACE_Based_Pointer_Repository_Rep::MAP_ITERATOR iter (this->rep_->addr_map_);
+ iter.next (ce) != 0;
+ iter.advance ())
+ // Check to see if <addr> is within any of the regions.
+ if (addr >= ce->ext_id_
+ && addr < ((char *) ce->ext_id_ + ce->int_id_))
+ {
+ // Assign the base address.
+ base_addr = ce->ext_id_;
+ return 1;
+ }
+
+ // Assume base address 0 (e.g., if new'ed).
+ base_addr = 0;
+ return 0;
+}
+
+// Bind a new entry to the repository or update the size of an
+// existing entry.
+
+int
+ACE_Based_Pointer_Repository::bind (void *addr,
+ size_t size)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Repository::bind");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->rep_->lock_, -1);
+
+ return this->rep_->addr_map_.rebind (addr, size);
+}
+
+// Unbind a base from the repository.
+
+int
+ACE_Based_Pointer_Repository::unbind (void *addr)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Repository::unbind");
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, mon, this->rep_->lock_, -1);
+ ACE_Based_Pointer_Repository_Rep::MAP_ENTRY *ce = 0;
+
+ // Search for service handlers that requested notification.
+
+ for (ACE_Based_Pointer_Repository_Rep::MAP_ITERATOR iter (this->rep_->addr_map_);
+ iter.next (ce) != 0;
+ iter.advance ())
+ {
+ // Check to see if <addr> is within any of the regions and if
+ // so, unbind the key from the map.
+ if (addr >= ce->ext_id_
+ && addr < ((char *) ce->ext_id_ + ce->int_id_))
+ // Unbind base address.
+ return this->rep_->addr_map_.unbind (ce->ext_id_);
+ }
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Singleton <ACE_Based_Pointer_Repository, ACE_SYNCH_RW_MUTEX>;
+template class ACE_Map_Entry<void *, size_t>;
+template class ACE_Map_Manager<void *, size_t, ACE_Null_Mutex>;
+template class ACE_Map_Iterator<void *, size_t, ACE_Null_Mutex>;
+template class ACE_Map_Reverse_Iterator<void *, size_t, ACE_Null_Mutex>;
+template class ACE_Map_Iterator_Base<void *, size_t, ACE_Null_Mutex>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Singleton <ACE_Based_Pointer_Repository, ACE_SYNCH_RW_MUTEX>
+#pragma instantiate ACE_Map_Entry<void *, size_t>
+#pragma instantiate ACE_Map_Manager<void *, size_t, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator<void *, size_t, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Reverse_Iterator<void *, size_t, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator_Base<void *, size_t, ACE_Null_Mutex>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Memory/Based_Pointer_Repository.h b/ace/Memory/Based_Pointer_Repository.h
new file mode 100644
index 00000000000..2b14c52fa9f
--- /dev/null
+++ b/ace/Memory/Based_Pointer_Repository.h
@@ -0,0 +1,70 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Based_Pointer_Repository.h
+ *
+ * $Id$
+ *
+ * @author Dietrich Quehl <Dietrich.Quehl@med.siemens.de>
+ * @author Douglas C. Schmidt <schmidt@.cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_BASED_POINTER_REPOSITORY_H
+#define ACE_BASED_POINTER_REPOSITORY_H
+#include "ace/pre.h"
+
+#include "ace/OS.h" // Need ACE_Export
+
+// Forward decl., using the "Cheshire Cat" technique.
+class ACE_Based_Pointer_Repository_Rep;
+
+/**
+ * @class ACE_Based_Pointer_Repository
+ *
+ * @brief Maps pointers to the base address of the region to which each
+ * pointer belongs.
+ */
+class ACE_Export ACE_Based_Pointer_Repository
+{
+public:
+ // = Use <ACE_Null_Mutex> to allow locking while iterating.
+
+ // = Initialization and termination methods.
+ ACE_Based_Pointer_Repository (void);
+ ~ACE_Based_Pointer_Repository (void);
+
+ // = Search structure methods.
+ /**
+ * Return the appropriate <base_addr> region that contains <addr>.
+ * Returns 1 on success and 0 if the <addr> isn't contained in any
+ * <base_addr> region.
+ */
+ int find (void *addr,
+ void *&base_addr);
+
+ /// Bind a new entry to the repository or update the size of an
+ /// existing entry. Returns 0 on success and -1 on failure.
+ int bind (void *addr,
+ size_t size);
+
+ /// Unbind from the repository the <base_addr> that <addr> is
+ /// contained within.
+ int unbind (void *addr);
+
+private:
+ /// Use the "Cheshire-Cat" technique to hide the implementation in
+ /// order to avoid circular #include dependencies.
+ ACE_Based_Pointer_Repository_Rep *rep_;
+};
+
+#include "ace/Singleton.h"
+
+/// Provide a Singleton access point to the based pointer repository.
+typedef ACE_Singleton<ACE_Based_Pointer_Repository, ACE_SYNCH_RW_MUTEX>
+ ACE_BASED_POINTER_REPOSITORY;
+
+#include "ace/post.h"
+#endif /* ACE_BASED_POINTER_REPOSITORY_H */
diff --git a/ace/Memory/Based_Pointer_T.cpp b/ace/Memory/Based_Pointer_T.cpp
new file mode 100644
index 00000000000..5bf6352b406
--- /dev/null
+++ b/ace/Memory/Based_Pointer_T.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+#ifndef ACE_BASED_POINTER_T_CPP
+#define ACE_BASED_POINTER_T_CPP
+
+#include "ace/Based_Pointer_T.h"
+#include "ace/Based_Pointer_Repository.h"
+#include "ace/Log_Msg.h"
+
+# define ACE_TRACEX(X) ACE_Trace ____ (ACE_LIB_TEXT (X), __LINE__, ACE_LIB_TEXT (__FILE__))
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Based_Pointer_T.i"
+#endif /* __ACE_INLINE__ */
+
+template <class CONCRETE>
+ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer (void)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer");
+}
+
+template <class CONCRETE> void
+ACE_Based_Pointer_Basic<CONCRETE>::dump (void) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntarget_ = %d\n"), this->target_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("base_offset_ = %d\n"), this->base_offset_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("computed pointer = %x\n"), (CONCRETE *)(ACE_COMPUTE_BASED_POINTER (this))));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer (CONCRETE *initial)
+ : ACE_Based_Pointer_Basic<CONCRETE> (initial)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer (const void* base_addr, int)
+ : ACE_Based_Pointer_Basic<CONCRETE> (base_addr, 0)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic (void)
+ : target_ (0),
+ base_offset_ (0)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+ void *base_addr = 0;
+
+ // Find the base address associated with our <this> pointer. Note
+ // that it's ok for <find> to return 0, which simply indicates that
+ // the address is not in memory-mapped virtual address space.
+ ACE_BASED_POINTER_REPOSITORY::instance ()->find (this,
+ base_addr);
+ this->base_offset_ = (char *) this - (char *) base_addr;
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic (const void *base_addr, int)
+ : target_ (0),
+ base_offset_ (0)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+ this->base_offset_ = (char *) this - (char *) base_addr;
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic (CONCRETE *rhs)
+ : target_ (0),
+ base_offset_ (0)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+
+ if (rhs == 0)
+ // Store a value of <target_> that indicate "NULL" pointer.
+ this->target_ = -1;
+ else
+ {
+ void *base_addr = 0;
+
+ // Find the base address associated with the <addr> pointer.
+ // Note that it's ok for <find> to return 0, which simply
+ // indicates that the address is not in memory-mapped virtual
+ // address space.
+ ACE_BASED_POINTER_REPOSITORY::instance ()->find (this,
+ base_addr);
+ this->base_offset_ = (char *) this - (char *) base_addr;
+ this->target_ = ((char *) rhs - (char *) base_addr);
+ }
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic (const ACE_Based_Pointer_Basic<CONCRETE> &)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::ACE_Based_Pointer_Basic");
+
+ ACE_ASSERT (0); // not implemented.
+}
+
+template <class CONCRETE>
+ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer (const ACE_Based_Pointer<CONCRETE> &rhs)
+ : ACE_Based_Pointer_Basic<CONCRETE> (rhs)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::ACE_Based_Pointer");
+ ACE_ASSERT (0); // not implemented.
+}
+
+#endif /* ACE_BASED_POINTER_T_CPP */
diff --git a/ace/Memory/Based_Pointer_T.h b/ace/Memory/Based_Pointer_T.h
new file mode 100644
index 00000000000..c8a8dcf55be
--- /dev/null
+++ b/ace/Memory/Based_Pointer_T.h
@@ -0,0 +1,198 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Based_Pointer_T.h
+ *
+ * $Id$
+ *
+ * @author Dietrich Quehl <Dietrich.Quehl@med.siemens.de>
+ * @author Douglas C. Schmidt <schmidt@.cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_BASED_POINTER_T_H
+#define ACE_BASED_POINTER_T_H
+#include "ace/pre.h"
+
+#include "ace/OS.h" // Need ACE_Export
+
+#if defined (_MSC_VER)
+// Suppress warning e.g. "return type for
+// 'ACE_Based_Pointer<long>::operator ->' is 'long *' (i.e., not a UDT
+// or reference to a UDT. Will produce errors if applied using infix
+// notation)"
+#pragma warning(disable: 4284)
+#endif /* _MSC_VER */
+
+/**
+ * @class ACE_Based_Pointer_Basic
+ *
+ * @brief A proxy that keeps track of the relative offset of a "pointer"
+ * from its base address.
+ * This class makes it possible to transparently use "pointers" in
+ * shared memory as easily as programming with pointers to local
+ * memory. In particular, we don't need to ensure that the base
+ * addresses of all the pointers are mapped into separate
+ * processes at the same absolute memory base address.
+ */
+template <class CONCRETE>
+class ACE_Based_Pointer_Basic
+{
+public:
+ /**
+ * This constructor initializes the <base_offset_> by asking the
+ * <ACE_BASED_POINTER_REPOSITORY> Singleton for the base address of
+ * the memory region within which it is instantiated. Two results
+ * are possible:
+ *
+ * 1. An <ACE_*_Memory_Pool> has stored a base address/size pair and the
+ * new based-pointer instance is located between the base address and
+ * the base address + size - 1. In this case, the repository
+ * returns the base address.
+ *
+ * 2. No suitable address/size pair was found. The repository
+ * assumes an address in the regular (not mapped) virtual address
+ * space of the process and returns 0. In this case, the
+ * based-pointer uses its address as an offset to it's base
+ * address 0.
+ */
+ ACE_Based_Pointer_Basic (void);
+
+ /**
+ * Initialize this object using the <initial> pointer. This
+ * constructor initializes the <base_offset_> by asking the
+ * <ACE_BASED_POINTER_REPOSITORY> Singleton for the base address of
+ * the memory region within which it is instantiated. Three results
+ * are possible:
+ *
+ * 1. An <ACE_*_Memory_Pool> has stored a base address/size pair and the
+ * new based-pointer instance is located between the base address and
+ * the base address + size - 1. In this case, the repository
+ * returns the base address.
+ *
+ * 2. No suitable address/size pair was found. The repository
+ * assumes an address in the regular (not mapped) virtual address
+ * space of the process and returns 0. In this case, the
+ * based-pointer uses its address as an offset to its base
+ * address 0.
+ *
+ * 3. If <initial> is 0 then set the value of <target_> to -1, which
+ * indicates a "NULL" pointer.
+ */
+ ACE_Based_Pointer_Basic (CONCRETE *initial);
+
+ /// Copy constructor.
+ ACE_Based_Pointer_Basic (const ACE_Based_Pointer_Basic<CONCRETE> &);
+
+ /// Constructor for know base address. <o> is only used to
+ /// resolve overload ambiguity.
+ ACE_Based_Pointer_Basic (const void *base_addr, int o);
+
+ /// Pseudo-assignment operator.
+ void operator = (CONCRETE *from);
+
+ /// Pseudo-assignment operator.
+ void operator = (const ACE_Based_Pointer_Basic<CONCRETE> &);
+
+ /// Dereference operator.
+ CONCRETE operator * (void) const;
+
+ /// Less than operator.
+ int operator < (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Less than or equal operator.
+ int operator <= (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Greater than operator.
+ int operator > (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Greater than or equal operator.
+ int operator >= (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Equality operator.
+ int operator == (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Inequality operator.
+ int operator != (const ACE_Based_Pointer_Basic<CONCRETE> &) const;
+
+ /// Subscript operator.
+ CONCRETE operator [](int index) const;
+
+ /// Increment operator.
+ void operator+= (int index);
+
+ /// Returns the underlying memory address of the smart pointer.
+ operator CONCRETE *() const;
+
+ /// Returns the underlying memory address of the smart pointer.
+ CONCRETE *addr (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+protected:
+ long target_;
+
+ /// Keep track of our offset from the base pointer.
+ long base_offset_;
+};
+
+/**
+ * @class ACE_Based_Pointer
+ *
+ * @brief A smart proxy that keeps track of the relative offset of a
+ * "pointer" from its base address.
+ *
+ * This class makes it possible to transparently use "pointers" in
+ * shared memory as easily as programming with pointers to local
+ * memory by overloading the C++ delegation operator ->().
+ */
+template <class CONCRETE>
+class ACE_Based_Pointer : public ACE_Based_Pointer_Basic<CONCRETE>
+{
+public:
+ // = Initialization method.
+ /// Constructor. See constructor for <ACE_Based_Pointer_Basic> for
+ /// details.
+ ACE_Based_Pointer (void);
+
+ /// Initialize this object using the <initial> pointer. See
+ /// constructor for <ACE_Based_Pointer_Basic> for details.
+ ACE_Based_Pointer (CONCRETE *initial);
+
+ /// Initialize this object with known <base_addr>. <dummy> is
+ /// a dummy value used to resolve overload ambiguity and it
+ /// otherwise ignored.
+ ACE_Based_Pointer (const void *base_addr, int dummy);
+
+ /// Copy constructor (not implemented yet).
+ ACE_Based_Pointer (const ACE_Based_Pointer<CONCRETE> &);
+
+ /// Assignment operator.
+ void operator = (const ACE_Based_Pointer<CONCRETE> &);
+
+ /// Pseudo-assignment operator.
+ void operator = (CONCRETE *from);
+
+ /// The C++ "delegation operator".
+ CONCRETE *operator-> (void);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Based_Pointer_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Based_Pointer_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Based_Pointer_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_BASED_POINTER_T_H */
diff --git a/ace/Memory/Based_Pointer_T.i b/ace/Memory/Based_Pointer_T.i
new file mode 100644
index 00000000000..1d99f9ecaa8
--- /dev/null
+++ b/ace/Memory/Based_Pointer_T.i
@@ -0,0 +1,136 @@
+/* -*- C++ -*- */
+// $Id$
+
+#define ACE_COMPUTE_BASED_POINTER(P) (((char *) (P) - (P)->base_offset_) + (P)->target_)
+
+template <class CONCRETE> ACE_INLINE CONCRETE *
+ACE_Based_Pointer<CONCRETE>::operator->(void)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::operator->");
+ return (CONCRETE *)(ACE_COMPUTE_BASED_POINTER (this));
+}
+
+template <class CONCRETE> ACE_INLINE void
+ACE_Based_Pointer_Basic<CONCRETE>::operator = (CONCRETE *rhs)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator =");
+ if (rhs == 0)
+ // Store a value of <target_> that indicate "NULL" pointer.
+ this->target_ = -1;
+ else
+ this->target_ = ((char *) rhs
+ - ((char *) this - this->base_offset_));
+}
+
+template <class CONCRETE> ACE_INLINE void
+ACE_Based_Pointer<CONCRETE>::operator = (CONCRETE *rhs)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::operator =");
+ if (rhs == 0)
+ // Store a value of <target_> that indicate "NULL" pointer.
+ this->target_ = -1;
+ else
+ this->target_ = ((char *) rhs
+ - ((char *) this - this->base_offset_));
+}
+
+template <class CONCRETE> ACE_INLINE CONCRETE
+ACE_Based_Pointer_Basic<CONCRETE>::operator *(void) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator *");
+ return *ACE_reinterpret_cast (CONCRETE *,
+ ACE_COMPUTE_BASED_POINTER (this));
+}
+
+template <class CONCRETE> ACE_INLINE CONCRETE *
+ACE_Based_Pointer_Basic<CONCRETE>::addr (void) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::addr");
+
+ if (this->target_ == -1)
+ return 0;
+ else
+ return ACE_reinterpret_cast (CONCRETE *,
+ ACE_COMPUTE_BASED_POINTER (this));
+}
+
+template <class CONCRETE> ACE_INLINE
+ACE_Based_Pointer_Basic<CONCRETE>::operator CONCRETE *() const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator CONCRETE *()");
+
+ return this->addr ();
+}
+
+template <class CONCRETE> ACE_INLINE CONCRETE
+ACE_Based_Pointer_Basic<CONCRETE>::operator [] (int index) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator []");
+ CONCRETE *c = ACE_reinterpret_cast (CONCRETE *,
+ ACE_COMPUTE_BASED_POINTER (this));
+ return c[index];
+}
+
+template <class CONCRETE> ACE_INLINE void
+ACE_Based_Pointer_Basic<CONCRETE>::operator += (int index)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator +=");
+ this->base_offset_ += (index * sizeof (CONCRETE));
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator == (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator ==");
+ return ACE_COMPUTE_BASED_POINTER (this) == ACE_COMPUTE_BASED_POINTER (&rhs);
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator != (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator !=");
+ return !(*this == rhs);
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator < (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator <");
+ return ACE_COMPUTE_BASED_POINTER (this) < ACE_COMPUTE_BASED_POINTER (&rhs);
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator <= (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator <=");
+ return ACE_COMPUTE_BASED_POINTER (this) <= ACE_COMPUTE_BASED_POINTER (&rhs);
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator > (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator >");
+ return ACE_COMPUTE_BASED_POINTER (this) > ACE_COMPUTE_BASED_POINTER (&rhs);
+}
+
+template <class CONCRETE> ACE_INLINE int
+ACE_Based_Pointer_Basic<CONCRETE>::operator >= (const ACE_Based_Pointer_Basic<CONCRETE> &rhs) const
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator >=");
+ return ACE_COMPUTE_BASED_POINTER (this) >= ACE_COMPUTE_BASED_POINTER (&rhs);
+}
+
+template <class CONCRETE> ACE_INLINE void
+ACE_Based_Pointer_Basic<CONCRETE>::operator= (const ACE_Based_Pointer_Basic<CONCRETE> &rhs)
+{
+ ACE_TRACE ("ACE_Based_Pointer_Basic<CONCRETE>::operator=");
+ *this = rhs.addr ();
+}
+
+template <class CONCRETE> ACE_INLINE void
+ACE_Based_Pointer<CONCRETE>::operator= (const ACE_Based_Pointer<CONCRETE> &rhs)
+{
+ ACE_TRACE ("ACE_Based_Pointer<CONCRETE>::operator=");
+ *this = rhs.addr ();
+}
+
diff --git a/ace/Memory/Bound_Ptr.h b/ace/Memory/Bound_Ptr.h
new file mode 100644
index 00000000000..094bdb6b8d2
--- /dev/null
+++ b/ace/Memory/Bound_Ptr.h
@@ -0,0 +1,300 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Bound_Ptr.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef ACE_BOUND_PTR_H
+#define ACE_BOUND_PTR_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+#include "ace/Auto_Ptr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Bound_Ptr_Counter
+ *
+ * @brief An ACE_Bound_Ptr_Counter<ACE_LOCK> object encapsulates an object
+ * reference count. Do not use this class directly, use ACE_Strong_Bound_Ptr
+ * or ACE_Weak_Bound_Ptr instead.
+ */
+template <class ACE_LOCK>
+class ACE_Bound_Ptr_Counter
+{
+public:
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ ACE_Bound_Ptr_Counter (int init_obj_ref_count = 0);
+ ~ACE_Bound_Ptr_Counter (void);
+
+ /// Create a ACE_Bound_Ptr_Counter<ACE_LOCK> and initialize the reference
+ /// count to indicate ownership by a strong pointer.
+ static ACE_Bound_Ptr_Counter<ACE_LOCK> *create_strong (void);
+
+ /// Increase both the object and counter reference counts and return the new
+ /// object reference count. A return value of -1 indicates that the object
+ /// has already been destroyed.
+ static int attach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);
+
+ /// Decreases both the object and counter reference counts and deletes
+ /// whichever has no more references. Returns the new object reference count.
+ static int detach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);
+
+ /// Create a ACE_Bound_Ptr_Counter<ACE_LOCK> and initialize the reference
+ /// count to indicate no ownership.
+ static ACE_Bound_Ptr_Counter<ACE_LOCK> *create_weak (void);
+
+ /// Increase the counter reference count and return argument.
+ static void attach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);
+
+ /// Decreases the counter reference count and deletes the counter if it has
+ /// no more references.
+ static void detach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);
+
+ /// Determine whether the object has been deleted.
+ static int object_was_deleted (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);
+
+private:
+ /// Allocate a new ACE_Bound_Ptr_Counter<ACE_LOCK> instance, returning NULL
+ /// if it cannot be created.
+ static ACE_Bound_Ptr_Counter<ACE_LOCK> *internal_create (int init_obj_ref_count);
+
+ /// Reference count of underlying object. Is set to -1 once the object has
+ /// been destroyed to indicate to all weak pointers that it is no longer valid.
+ int obj_ref_count_;
+
+ /// Reference count of this counter.
+ int self_ref_count_;
+
+ /// Mutex variable to synchronize access to the reference counts.
+ ACE_LOCK lock_;
+};
+
+// Forward decl.
+template <class X, class ACE_LOCK> class ACE_Weak_Bound_Ptr;
+
+/**
+ * @class ACE_Strong_Bound_Ptr
+ *
+ * @brief This class implements support for a reference counted pointer.
+ * Assigning or copying instances of an ACE_Strong_Bound_Ptr will
+ * automatically increment the reference count of the underlying object.
+ * When the last instance of an ACE_Strong_Bound_Ptr that references a
+ * particular object is destroyed or overwritten, it will invoke delete
+ * on its underlying pointer.
+ */
+template <class X, class ACE_LOCK>
+class ACE_Strong_Bound_Ptr
+{
+public:
+ /// Constructor that initializes an ACE_Strong_Bound_Ptr to point to the
+ /// object <p> immediately.
+ ACE_EXPLICIT ACE_Strong_Bound_Ptr (X *p = 0);
+
+ /// Constructor that initializes an ACE_Strong_Bound_Ptr by stealing
+ /// ownership of an object from an auto_ptr.
+ ACE_EXPLICIT ACE_Strong_Bound_Ptr (auto_ptr<X> p);
+
+ /// Copy constructor binds <this> and <r> to the same object.
+ ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Constructor binds <this> and <r> to the same object.
+ ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Destructor.
+ ~ACE_Strong_Bound_Ptr (void);
+
+ /// Assignment operator that binds <this> and <r> to the same object.
+ void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Assignment operator that binds <this> and <r> to the same object.
+ void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Equality operator that returns 1 if both ACE_Strong_Bound_Ptr instances
+ /// point to the same underlying object. Attention: It also returns 1 if
+ /// both objects have just been instantiated and not used yet.
+ int operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns 1 if the ACE_Strong_Bound_Ptr and
+ /// ACE_Weak_Bound_Ptr objects point to the same underlying object.
+ /// Attention: It also returns 1 if both objects have just been
+ /// instantiated and not used yet.
+ int operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns 1 if the ACE_Strong_Bound_Ptr and the raw
+ /// pointer point to the same underlying object.
+ int operator == (X *p) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (X *p) const;
+
+ /// Redirection operator
+ X *operator-> (void) const;
+
+ /// Dereference operator
+ X &operator * (void) const;
+
+ /// Get the pointer value.
+ X *get (void);
+
+ /// Resets the ACE_Strong_Bound_Ptr to refer to a different underlying
+ /// object.
+ void reset (X *p = 0);
+
+ /// Resets the ACE_Strong_Bound_Ptr to refer to a different underlying
+ /// object, ownership of which is stolen from the auto_ptr.
+ void reset (auto_ptr<X> p);
+
+ /// Allows us to check for NULL on all ACE_Strong_Bound_Ptr objects.
+ int null (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ friend class ACE_Weak_Bound_Ptr<X, ACE_LOCK>;
+
+ /// The ACE_Bound_Ptr_Counter type.
+ typedef ACE_Bound_Ptr_Counter<ACE_LOCK> COUNTER;
+
+ /// The reference counter.
+ COUNTER *counter_;
+
+ /// The underlying object.
+ X *ptr_;
+};
+
+/**
+ * @class ACE_Weak_Bound_Ptr
+ *
+ * @brief This class implements support for a weak pointer that complements
+ * ACE_Strong_Bound_Ptr. Unlike ACE_Strong_Bound_Ptr, assigning or copying
+ * instances of an ACE_Weak_Bound_Ptr will not automatically increment the
+ * reference count of the underlying object. What ACE_Weak_Bound_Ptr does is
+ * preserve the knowledge that the object is in fact reference counted, and
+ * thus provides an alternative to raw pointers where non-ownership
+ * associations must be maintained. When the last instance of an
+ * ACE_Strong_Bound_Ptr that references a particular object is destroyed or
+ * overwritten, the corresponding ACE_Weak_Bound_Ptr instances are set to
+ * null.
+ */
+template <class X, class ACE_LOCK>
+class ACE_Weak_Bound_Ptr
+{
+public:
+ /// Constructor that initializes an ACE_Weak_Bound_Ptr to point to the
+ /// object <p> immediately.
+ ACE_EXPLICIT ACE_Weak_Bound_Ptr (X *p = 0);
+
+ /// Copy constructor binds <this> and <r> to the same object.
+ ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Constructor binds <this> and <r> to the same object.
+ ACE_Weak_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Destructor.
+ ~ACE_Weak_Bound_Ptr (void);
+
+ /// Assignment operator that binds <this> and <r> to the same object.
+ void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Assignment operator that binds <this> and <r> to the same object.
+ void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);
+
+ /// Equality operator that returns 1 if both ACE_Weak_Bound_Ptr objects
+ /// point to the same underlying object. Attention: It also returns 1 if
+ /// both objects have just been instantiated and not used yet.
+ int operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns 1 if the ACE_Weak_Bound_Ptr and
+ /// ACE_Strong_Bound_Ptr objects point to the same underlying object.
+ /// Attention: It also returns 1 if both objects have just been instantiated
+ /// and not used yet.
+ int operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Equality operator that returns 1 if the ACE_Weak_Bound_Ptr and the raw
+ /// pointer point to the same underlying object.
+ int operator == (X *p) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;
+
+ /// Inequality operator, which is the opposite of equality.
+ int operator != (X *p) const;
+
+ /// Redirection operator. It returns a temporary strong pointer and makes
+ /// use of the chaining properties of operator-> to ensure that the
+ /// underlying object does not disappear while you are using it. If
+ /// you are certain of the lifetimes of the object, and do not want to incur
+ /// the locking overhead, then use the unsafe_get method instead.
+ ACE_Strong_Bound_Ptr<X, ACE_LOCK> operator-> (void) const;
+
+ /// Obtain a strong pointer corresponding to this weak pointer. This function
+ /// is useful to create a temporary strong pointer for conversion to a
+ /// reference.
+ ACE_Strong_Bound_Ptr<X, ACE_LOCK> strong (void) const;
+
+ /// Get the pointer value. Warning: this does not affect the reference count
+ /// of the underlying object, so it may disappear on you while you are using
+ /// it if you are not careful.
+ X *unsafe_get (void) const;
+
+ /// Resets the ACE_Weak_Bound_Ptr to refer to a different underlying object.
+ void reset (X *p = 0);
+
+ /// Increment the reference count on the underlying object. Returns the new
+ /// reference count on the object. This function may be used to integrate the
+ /// bound pointers into an external reference counting mechanism such as
+ /// those used by COM or CORBA servants.
+ int add_ref (void);
+
+ /// Decrement the reference count on the underlying object, which is deleted
+ /// if the count has reached zero. Returns the new reference count on the
+ /// object. This function may be used to integrate the bound pointers into an
+ /// external reference counting mechanism such as those used by COM or CORBA
+ /// servants.
+ int remove_ref (void);
+
+ /// Allows us to check for NULL on all ACE_Weak_Bound_Ptr objects.
+ int null (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ friend class ACE_Strong_Bound_Ptr<X, ACE_LOCK>;
+
+ /// The ACE_Bound_Ptr_Counter type.
+ typedef ACE_Bound_Ptr_Counter<ACE_LOCK> COUNTER;
+
+ /// The reference counter.
+ COUNTER *counter_;
+
+ /// The underlying object.
+ X *ptr_;
+};
+
+#include "ace/Bound_Ptr.i"
+
+#include "ace/post.h"
+#endif /* ACE_BOUND_PTR_H */
diff --git a/ace/Memory/Bound_Ptr.i b/ace/Memory/Bound_Ptr.i
new file mode 100644
index 00000000000..964c7975dd9
--- /dev/null
+++ b/ace/Memory/Bound_Ptr.i
@@ -0,0 +1,481 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Bound_Ptr.i
+
+#include "Synch_T.h"
+
+template <class ACE_LOCK> inline ACE_Bound_Ptr_Counter<ACE_LOCK> *
+ACE_Bound_Ptr_Counter<ACE_LOCK>::internal_create (int init_obj_ref_count)
+{
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *temp = 0;
+ ACE_NEW_RETURN (temp,
+ ACE_Bound_Ptr_Counter<ACE_LOCK> (init_obj_ref_count),
+ 0);
+ return temp;
+}
+
+template <class ACE_LOCK> inline ACE_Bound_Ptr_Counter<ACE_LOCK> *
+ACE_Bound_Ptr_Counter<ACE_LOCK>::create_strong (void)
+{
+ // Set initial object reference count to 1.
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *temp = internal_create (1);
+#if defined (ACE_NEW_THROWS_EXCEPTIONS)
+ if (temp == 0)
+ ACE_throw_bad_alloc;
+#else
+ ACE_ASSERT (temp != 0);
+#endif /* ACE_NEW_THROWS_EXCEPTIONS */
+ return temp;
+}
+
+
+
+template <class ACE_LOCK> inline int
+ACE_Bound_Ptr_Counter<ACE_LOCK>::attach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK>* counter)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, -1);
+
+ // Can't attach a strong pointer to an object that has already been deleted.
+ if (counter->obj_ref_count_ == -1)
+ return -1;
+
+ int new_obj_ref_count = ++counter->obj_ref_count_;
+ ++counter->self_ref_count_;
+
+ return new_obj_ref_count;
+}
+
+template <class ACE_LOCK> inline int
+ACE_Bound_Ptr_Counter<ACE_LOCK>::detach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK>* counter)
+{
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *counter_del = 0;
+ int new_obj_ref_count;
+
+ {
+ ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, -1);
+
+ if ((new_obj_ref_count = --counter->obj_ref_count_) == 0)
+ // Change the object reference count to -1 to indicate that the
+ // object has been deleted, as opposed to a weak pointer that
+ // simply hasn't had any strong pointers created from it yet.
+ counter->obj_ref_count_ = -1;
+
+ if (--counter->self_ref_count_ == 0)
+ // Since counter contains the lock held by the ACE_Guard, the
+ // guard needs to be released before freeing the memory holding
+ // the lock. So save the pointer to free, then release, then
+ // free.
+ counter_del = counter;
+
+ } // Release the lock
+
+ delete counter_del;
+
+ return new_obj_ref_count;
+}
+
+template <class ACE_LOCK> inline ACE_Bound_Ptr_Counter<ACE_LOCK> *
+ACE_Bound_Ptr_Counter<ACE_LOCK>::create_weak (void)
+{
+ // Set initial object reference count to 0.
+
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *temp = internal_create (0);
+#if defined (ACE_NEW_THROWS_EXCEPTIONS)
+ if (temp == 0)
+ ACE_throw_bad_alloc;
+#else
+ ACE_ASSERT (temp != 0);
+#endif /* ACE_NEW_THROWS_EXCEPTIONS */
+ return temp;
+}
+
+template <class ACE_LOCK> inline void
+ACE_Bound_Ptr_Counter<ACE_LOCK>::attach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK>* counter)
+{
+ ACE_GUARD (ACE_LOCK, guard, counter->lock_);
+
+ ++counter->self_ref_count_;
+}
+
+template <class ACE_LOCK> inline void
+ACE_Bound_Ptr_Counter<ACE_LOCK>::detach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK>* counter)
+{
+ ACE_Bound_Ptr_Counter<ACE_LOCK> *counter_del = 0;
+
+ {
+ ACE_GUARD (ACE_LOCK, guard, counter->lock_);
+
+ if (--counter->self_ref_count_ == 0)
+ // Since counter contains the lock held by the ACE_Guard, the
+ // guard needs to be released before freeing the memory holding
+ // the lock. So save the pointer to free, then release, then
+ // free.
+ counter_del = counter;
+
+ } // Release the lock
+
+ delete counter_del;
+}
+
+template <class ACE_LOCK> inline int
+ACE_Bound_Ptr_Counter<ACE_LOCK>::object_was_deleted (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, guard, counter->lock_, 0);
+
+ return counter->obj_ref_count_ == -1;
+}
+
+template <class ACE_LOCK> inline
+ACE_Bound_Ptr_Counter<ACE_LOCK>::ACE_Bound_Ptr_Counter (int init_obj_ref_count)
+ : obj_ref_count_ (init_obj_ref_count),
+ self_ref_count_ (1)
+{
+}
+
+template <class ACE_LOCK> inline
+ACE_Bound_Ptr_Counter<ACE_LOCK>::~ACE_Bound_Ptr_Counter (void)
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::ACE_Strong_Bound_Ptr (X *p)
+ : counter_ (COUNTER::create_strong ()),
+ ptr_ (p)
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::ACE_Strong_Bound_Ptr (auto_ptr<X> p)
+ : counter_ (COUNTER::create_strong ()),
+ ptr_ (p.release())
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r)
+ : counter_ (r.counter_),
+ ptr_ (r.ptr_)
+{
+ COUNTER::attach_strong (this->counter_);
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r)
+ : counter_ (r.counter_),
+ ptr_ (r.ptr_)
+{
+ // When creating a strong pointer from a weak one we can't assume that the
+ // underlying object still exists. Therefore we must check for a return value
+ // of -1, which indicates that the object has been destroyed.
+ if (COUNTER::attach_strong (this->counter_) == -1)
+ {
+ // Underlying object has already been deleted, so set this pointer to null.
+ this->counter_ = COUNTER::create_strong ();
+ this->ptr_ = 0;
+ }
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::~ACE_Strong_Bound_Ptr (void)
+{
+ if (COUNTER::detach_strong (this->counter_) == 0)
+ delete this->ptr_;
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &rhs)
+{
+ // This will work if &r == this, by first increasing the ref count
+
+ COUNTER *new_counter = rhs.counter_;
+ X* new_ptr = rhs.ptr_;
+ COUNTER::attach_strong (new_counter);
+ if (COUNTER::detach_strong (this->counter_) == 0)
+ delete this->ptr_;
+ this->counter_ = new_counter;
+ this->ptr_ = new_ptr;
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &rhs)
+{
+ // This will work if &r == this, by first increasing the ref count
+
+ COUNTER *new_counter = rhs.counter_;
+ X* new_ptr = rhs.ptr_;
+
+ // When creating a strong pointer from a weak one we can't assume that the
+ // underlying object still exists. Therefore we must check for a return value
+ // of -1, which indicates that the object has been destroyed.
+ if (COUNTER::attach_strong (new_counter) == -1)
+ {
+ // Underlying object has already been deleted, so set this pointer to null.
+ new_counter = COUNTER::create_strong ();
+ new_ptr = 0;
+ }
+
+ if (COUNTER::detach_strong (this->counter_) == 0)
+ delete this->ptr_;
+ this->counter_ = new_counter;
+ this->ptr_ = new_ptr;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator== (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ return this->ptr_ == r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator== (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // Use the weak pointer's operator== since it will check for null.
+ return r == *this;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator== (X *p) const
+{
+ return this->ptr_ == p;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator!= (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ return this->ptr_ != r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator!= (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // Use the weak pointer's operator!= since it will check for null.
+ return r != *this;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator!= (X *p) const
+{
+ return this->ptr_ != p;
+}
+
+template <class X, class ACE_LOCK> inline X *
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator-> (void) const
+{
+ return this->ptr_;
+}
+
+template<class X, class ACE_LOCK> inline X &
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::operator *() const
+{
+ return *this->ptr_;
+}
+
+template <class X, class ACE_LOCK> inline X*
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::get (void)
+{
+ return this->ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::null (void) const
+{
+ return this->ptr_ == 0;
+}
+
+template<class X, class ACE_LOCK> inline void
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::reset (X *p)
+{
+ COUNTER *old_counter = this->counter_;
+ X* old_ptr = this->ptr_;
+ this->counter_ = COUNTER::create_strong ();
+ this->ptr_ = p;
+ if (COUNTER::detach_strong (old_counter) == 0)
+ delete old_ptr;
+}
+
+template<class X, class ACE_LOCK> inline void
+ACE_Strong_Bound_Ptr<X, ACE_LOCK>::reset (auto_ptr<X> p)
+{
+ COUNTER *old_counter = this->counter_;
+ X* old_ptr = this->ptr_;
+ this->counter_ = COUNTER::create_strong ();
+ this->ptr_ = p.release ();
+ if (COUNTER::detach_strong (old_counter) == 0)
+ delete old_ptr;
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::ACE_Weak_Bound_Ptr (X *p)
+ : counter_ (COUNTER::create_weak ()),
+ ptr_ (p)
+{
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r)
+ : counter_ (r.counter_),
+ ptr_ (r.ptr_)
+{
+ COUNTER::attach_weak (this->counter_);
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::ACE_Weak_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r)
+ : counter_ (r.counter_),
+ ptr_ (r.ptr_)
+{
+ COUNTER::attach_weak (this->counter_);
+}
+
+template <class X, class ACE_LOCK> inline
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::~ACE_Weak_Bound_Ptr (void)
+{
+ COUNTER::detach_weak (this->counter_);
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &rhs)
+{
+ // This will work if &rhs == this, by first increasing the ref count
+ COUNTER *new_counter = rhs.counter_;
+ COUNTER::attach_weak (new_counter);
+ COUNTER::detach_weak (this->counter_);
+ this->counter_ = new_counter;
+ this->ptr_ = rhs.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline void
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &rhs)
+{
+ // This will work if &rhs == this, by first increasing the ref count
+ COUNTER *new_counter = rhs.counter_;
+ COUNTER::attach_weak (new_counter);
+ COUNTER::detach_weak (this->counter_);
+ this->counter_ = new_counter;
+ this->ptr_ = rhs.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator== (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return r.ptr_ == 0;
+
+ return this->ptr_ == r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator== (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return r.ptr_ == 0;
+
+ return this->ptr_ == r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator== (X *p) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return p == 0;
+
+ return this->ptr_ == p;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator!= (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return r.ptr_ != 0;
+
+ return this->ptr_ != r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator!= (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return r.ptr_ != 0;
+
+ return this->ptr_ != r.ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator!= (X *p) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return p != 0;
+
+ return this->ptr_ != p;
+}
+
+template <class X, class ACE_LOCK> inline ACE_Strong_Bound_Ptr<X, ACE_LOCK>
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::operator-> (void) const
+{
+ return ACE_Strong_Bound_Ptr<X, ACE_LOCK> (*this);
+}
+
+template <class X, class ACE_LOCK> inline ACE_Strong_Bound_Ptr<X, ACE_LOCK>
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::strong (void) const
+{
+ return ACE_Strong_Bound_Ptr<X, ACE_LOCK> (*this);
+}
+
+template <class X, class ACE_LOCK> inline X*
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::unsafe_get (void) const
+{
+ // We do not check if the object has been deleted, since this operation
+ // is defined to be unsafe!
+ return this->ptr_;
+}
+
+template <class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::null (void) const
+{
+ // A weak pointer must behave as though it is automatically set to null
+ // if the underlying object has been deleted.
+ if (COUNTER::object_was_deleted (this->counter_))
+ return 1;
+
+ return this->ptr_ == 0;
+}
+
+template<class X, class ACE_LOCK> inline void
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::reset (X *p)
+{
+ COUNTER *old_counter = this->counter_;
+ this->counter_ = COUNTER::create_weak ();
+ this->ptr_ = p;
+ COUNTER::detach_weak (old_counter);
+}
+
+template<class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::add_ref ()
+{
+ return COUNTER::attach_strong (counter_);
+}
+
+template<class X, class ACE_LOCK> inline int
+ACE_Weak_Bound_Ptr<X, ACE_LOCK>::remove_ref ()
+{
+ int new_obj_ref_count = COUNTER::detach_strong (counter_);
+ if (new_obj_ref_count == 0)
+ {
+ delete this->ptr_;
+ this->ptr_ = 0;
+ }
+ return new_obj_ref_count;
+}
diff --git a/ace/Memory/MEM_Acceptor.cpp b/ace/Memory/MEM_Acceptor.cpp
new file mode 100644
index 00000000000..0124fca8836
--- /dev/null
+++ b/ace/Memory/MEM_Acceptor.cpp
@@ -0,0 +1,239 @@
+// MEM_Acceptor.cpp
+// $Id$
+
+#include "ace/MEM_Acceptor.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Acceptor.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, MEM_Acceptor, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Acceptor)
+
+void
+ACE_MEM_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::dump");
+}
+
+// Do nothing routine for constructor.
+
+ACE_MEM_Acceptor::ACE_MEM_Acceptor (void)
+ : mmap_prefix_ (0),
+ malloc_options_ (ACE_DEFAULT_BASE_ADDR, 0),
+ preferred_strategy_ (ACE_MEM_IO::Reactive)
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::ACE_MEM_Acceptor");
+}
+
+ACE_MEM_Acceptor::~ACE_MEM_Acceptor (void)
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::~ACE_MEM_Acceptor");
+ delete[] this->mmap_prefix_;
+}
+
+// General purpose routine for performing server ACE_SOCK creation.
+
+ACE_MEM_Acceptor::ACE_MEM_Acceptor (const ACE_MEM_Addr &remote_sap,
+ int reuse_addr,
+ int backlog,
+ int protocol)
+ : mmap_prefix_ (0),
+ malloc_options_ (ACE_DEFAULT_BASE_ADDR, 0),
+ preferred_strategy_ (ACE_MEM_IO::Reactive)
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::ACE_MEM_Acceptor");
+ if (this->open (remote_sap,
+ reuse_addr,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_MEM_Acceptor::ACE_MEM_Acceptor")));
+}
+
+int
+ACE_MEM_Acceptor::open (const ACE_MEM_Addr &remote_sap,
+ int reuse_addr,
+ int back_log,
+ int protocol)
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::open");
+ return this->ACE_SOCK_Acceptor::open (remote_sap.get_local_addr (),
+ reuse_addr,
+ PF_INET,
+ back_log,
+ protocol);
+}
+
+// General purpose routine for accepting new connections.
+
+int
+ACE_MEM_Acceptor::accept (ACE_MEM_Stream &new_stream,
+ ACE_MEM_Addr *remote_sap,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle)
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::accept");
+
+ int *len_ptr = 0;
+ sockaddr *addr = 0;
+
+ int in_blocking_mode = 1;
+ if (this->shared_accept_start (timeout,
+ restart,
+ in_blocking_mode) == -1)
+ return -1;
+ else
+ {
+ do
+ new_stream.set_handle (ACE_OS::accept (this->get_handle (),
+ addr,
+ len_ptr));
+ while (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && restart != 0
+ && errno == EINTR
+ && timeout == 0);
+
+ if (remote_sap != 0)
+ {
+ ACE_INET_Addr temp (ACE_reinterpret_cast (sockaddr_in *, addr),
+ *len_ptr);
+ remote_sap->set_port_number(temp.get_port_number ());
+ }
+ }
+
+ if (this->shared_accept_finish (new_stream,
+ in_blocking_mode,
+ reset_new_handle) == -1)
+ return -1;
+
+ // Allocate 2 * MAXPATHLEN so we can accomodate the unique
+ // name that gets appended later
+ ACE_TCHAR buf [2 * MAXPATHLEN + 1];
+
+ ACE_INET_Addr local_addr;
+ if (new_stream.get_local_addr (local_addr) == -1)
+ return -1;
+
+ if (this->mmap_prefix_ != 0)
+ {
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s_%d_"),
+ this->mmap_prefix_,
+ local_addr.get_port_number ());
+ }
+ else
+ {
+ ACE_TCHAR name[25];
+ // - 24 is so we can append name to the end.
+ if (ACE_Lib_Find::get_temp_dir (buf, MAXPATHLEN - 24) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Temporary path too long, ")
+ ACE_LIB_TEXT ("defaulting to current directory\n")));
+ buf[0] = 0;
+ }
+
+ ACE_OS::sprintf (name,
+ ACE_LIB_TEXT ("MEM_Acceptor_%d_"),
+ local_addr.get_port_number ());
+ ACE_OS::strcat (buf, name);
+ }
+ ACE_TCHAR unique [MAXPATHLEN];
+ ACE_OS::unique_name (&new_stream, unique, MAXPATHLEN);
+
+ ACE_OS::strcat (buf, unique);
+
+ // Make sure we have a fresh start.
+ ACE_OS::unlink (buf);
+
+ new_stream.disable (ACE_NONBLOCK);
+ ACE_HANDLE new_handle = new_stream.get_handle ();
+
+ // Protocol negociation:
+ // Tell the client side what level of signaling strategy
+ // we support.
+ ACE_INT16 client_signaling =
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+ this->preferred_strategy_;
+#else
+ // We don't support MT.
+ ACE_MEM_IO::Reactive;
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+ if (ACE::send (new_handle, &client_signaling,
+ sizeof (ACE_INT16)) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Acceptor::accept error sending strategy\n")),
+ -1);
+
+ // Now we get the signaling strategy the client support.
+ if (ACE::recv (new_handle, &client_signaling,
+ sizeof (ACE_INT16)) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Acceptor::%p error receiving strategy\n"), "accept"),
+ -1);
+
+ // Client will decide what signaling strategy to use.
+
+ // Now set up the shared memory malloc pool.
+ if (new_stream.init (buf, ACE_static_cast (ACE_MEM_IO::Signal_Strategy, client_signaling),
+ &this->malloc_options_) == -1)
+ return -1;
+
+ // @@ Need to handle timeout here.
+ ACE_UINT16 buf_len = (ACE_OS::strlen (buf) + 1) * sizeof (ACE_TCHAR);
+
+ // No need to worry about byte-order because both parties should always
+ // be on the same machine.
+ if (ACE::send (new_handle, &buf_len, sizeof (ACE_UINT16)) == -1)
+ return -1;
+
+ // Now send the pathname of the mmap file.
+ if (ACE::send (new_handle, buf, buf_len) == -1)
+ return -1;
+ return 0;
+}
+
+int
+ACE_MEM_Acceptor::shared_accept_finish (ACE_MEM_Stream new_stream,
+ int in_blocking_mode,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_MEM_Acceptor::shared_accept_finish ()");
+
+ ACE_HANDLE new_handle = new_stream.get_handle ();
+
+ // Check to see if we were originally in blocking mode, and if so,
+ // set the <new_stream>'s handle and <this> handle to be in blocking
+ // mode.
+ if (in_blocking_mode)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ // Only disable ACE_NONBLOCK if we weren't in non-blocking mode
+ // originally.
+ ACE_Flag_Manip::clr_flags (this->get_handle (),
+ ACE_NONBLOCK);
+ ACE_Flag_Manip::clr_flags (new_handle,
+ ACE_NONBLOCK);
+ }
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ if (reset_new_handle)
+ // Reset the event association inherited by the new handle.
+ ::WSAEventSelect ((SOCKET) new_handle, 0, 0);
+#else
+ ACE_UNUSED_ARG (reset_new_handle);
+#endif /* ACE_WIN32 */
+ if (new_handle == ACE_INVALID_HANDLE)
+ return -1;
+
+ return 0;
+}
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_Acceptor.h b/ace/Memory/MEM_Acceptor.h
new file mode 100644
index 00000000000..b1521e3451f
--- /dev/null
+++ b/ace/Memory/MEM_Acceptor.h
@@ -0,0 +1,173 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_ACCEPTOR_H
+#define ACE_MEM_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/MEM_Stream.h"
+#include "ace/MEM_Addr.h"
+#include "ace/OS_QoS.h"
+
+// Forward decl.
+class ACE_Reactor;
+
+/**
+ * @class ACE_MEM_Acceptor
+ *
+ * @brief Defines the format and interface for the acceptor side of the
+ * local mmap stream.
+ *
+ * This class should be modified to prevent user passing a
+ * non-localhost endpoint as the acceptor listen point because
+ * it doesn't make any sense at all to make the listening
+ * endpoint visible (or connectable) anywhere outside of this
+ * machine. However, the type of endpoint is left as <ACE_Addr>
+ * so we can later changed to use UNIX sockets with mmap stream
+ * if so desired. (Currently, using UNIX socket with this class
+ * will not work.)
+ */
+class ACE_Export ACE_MEM_Acceptor : public ACE_SOCK_Acceptor
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_MEM_Acceptor (void);
+
+ /// destructor.
+ ~ACE_MEM_Acceptor (void);
+
+ /// Initiate a passive mode socket.
+ ACE_MEM_Acceptor (const ACE_MEM_Addr &remote_sap,
+ int reuse_addr = 0,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /**
+ * Initialize a passive-mode BSD-style acceptor socket (no QoS).
+ * <local_sap> is the address that we're going to listen for
+ * connections on. If <reuse_addr> is 1 then we'll use the
+ * <SO_REUSEADDR> to reuse this address. Returns 0 on success and
+ * -1 on failure.
+ */
+ int open (const ACE_MEM_Addr &local_sap,
+ int reuse_addr = 0,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Accept a new data transfer connection.
+ int accept (ACE_MEM_Stream &new_ipc_sap,
+ ACE_MEM_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0);
+
+ /// Perform operations that must occur after <ACE_OS::accept> is
+ /// called.
+ int shared_accept_finish (ACE_MEM_Stream new_stream,
+ int in_blocking_mode,
+ int reset_new_handle) const;
+
+ /**
+ * Accessor/mutator of mmap filename prefix. By default, the
+ * <mmap_prefix_> is not set and the mmap filename is
+ * ${(TMP|TEMP)}//ACE_MEM_Acceptor_(port-number)_(&stream),
+ * otherwise, it is <mmap_prefix_>_(port-number)_(&stream),
+ * <mmap_prefix_> should include _absolute_ path so the connector
+ * within the same host can located the mmap file. Example:
+ * /tmp/mmapfile.
+ */
+ const ACE_TCHAR *mmap_prefix (void) const;
+ void mmap_prefix (const ACE_TCHAR *prefix);
+
+ // Set/get the preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy (void) const;
+ void preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy);
+
+ /// Return the local endpoint address in the referenced <ACE_Addr>.
+ /// Returns 0 if successful, else -1.
+ int get_local_addr (ACE_MEM_Addr &) const;
+
+ /// Accessor to the mmap options.
+ ACE_MEM_SAP::MALLOC_OPTIONS& malloc_options (void);
+
+ // = Meta-type info
+ typedef ACE_MEM_Addr PEER_ADDR;
+ typedef ACE_MEM_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = The following methods should not be accessable externally
+ // because MEM_Acceptor do not support their semantics.
+ int open (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_INET,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ int open (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ int accept (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ int accept (ACE_SOCK_Stream &new_stream,
+ ACE_Accept_QoS_Params qos_params,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+private:
+ /// The filename prefix of the created mmap files. It should
+ /// contains the absolute path name of the file.
+ ACE_TCHAR *mmap_prefix_;
+
+ /// A cached MALLOC_OPTIONS. MEM_Accaptor use it to create the shared
+ /// mamory malloc upon every incoming connection.
+ ACE_MEM_SAP::MALLOC_OPTIONS malloc_options_;
+
+ // Preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Acceptor.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_MEM_ACCEPTOR_H */
diff --git a/ace/Memory/MEM_Acceptor.i b/ace/Memory/MEM_Acceptor.i
new file mode 100644
index 00000000000..1d18604ed29
--- /dev/null
+++ b/ace/Memory/MEM_Acceptor.i
@@ -0,0 +1,89 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_Acceptor.i
+
+ASYS_INLINE int
+ACE_MEM_Acceptor::open (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ return this->ACE_SOCK_Acceptor::open
+ (local_sap, protocolinfo, g, flags, reuse_addr, protocol_family,
+ backlog, protocol);
+}
+
+ASYS_INLINE int
+ACE_MEM_Acceptor::accept (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ return this->ACE_SOCK_Acceptor::accept
+ (new_stream, remote_addr, timeout, restart, reset_new_handle);
+}
+
+ASYS_INLINE int
+ACE_MEM_Acceptor::accept (ACE_SOCK_Stream &new_stream,
+ ACE_Accept_QoS_Params qos_params,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ return this->ACE_SOCK_Acceptor::accept
+ (new_stream, qos_params, remote_addr, timeout, restart, reset_new_handle);
+}
+
+ASYS_INLINE int
+ACE_MEM_Acceptor::get_local_addr (ACE_MEM_Addr &sap) const
+{
+ ACE_INET_Addr temp;
+
+ this->ACE_SOCK_Acceptor::get_local_addr (temp);
+ sap.set_port_number (temp.get_port_number ());
+ return 0;
+}
+
+ASYS_INLINE const ACE_TCHAR *
+ACE_MEM_Acceptor::mmap_prefix (void) const
+{
+ return this->mmap_prefix_;
+}
+
+ASYS_INLINE void
+ACE_MEM_Acceptor::mmap_prefix (const ACE_TCHAR *prefix)
+{
+ if (prefix == 0)
+ {
+ this->mmap_prefix_ = 0;
+ }
+ else
+ {
+ this->mmap_prefix_ = ACE::strnew (prefix);
+ }
+}
+
+ASYS_INLINE ACE_MEM_IO::Signal_Strategy
+ACE_MEM_Acceptor::preferred_strategy (void) const
+{
+ return this->preferred_strategy_;
+}
+
+ASYS_INLINE void
+ACE_MEM_Acceptor::preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy)
+{
+ this->preferred_strategy_ = strategy;
+}
+
+ASYS_INLINE ACE_MEM_SAP::MALLOC_OPTIONS &
+ACE_MEM_Acceptor::malloc_options (void)
+{
+ return this->malloc_options_;
+}
diff --git a/ace/Memory/MEM_Addr.cpp b/ace/Memory/MEM_Addr.cpp
new file mode 100644
index 00000000000..77363d66c4e
--- /dev/null
+++ b/ace/Memory/MEM_Addr.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+// Defines the Internet domain address family address format.
+
+#include "ace/MEM_Addr.h"
+#include "ace/Log_Msg.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/MEM_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, MEM_Addr, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Addr)
+
+// Transform the current address into string format.
+
+ACE_MEM_Addr::ACE_MEM_Addr (void)
+ : ACE_Addr (AF_INET, sizeof (ACE_MEM_Addr))
+{
+ // ACE_TRACE ("ACE_MEM_Addr::ACE_MEM_Addr");
+ this->initialize_local (0);
+}
+
+ACE_MEM_Addr::ACE_MEM_Addr (const ACE_MEM_Addr &sa)
+ : ACE_Addr (AF_INET, sizeof (ACE_MEM_Addr))
+{
+ ACE_TRACE ("ACE_MEM_Addr::ACE_MEM_Addr");
+ this->external_.set (sa.external_);
+ this->internal_.set (sa.internal_);
+}
+
+ACE_MEM_Addr::ACE_MEM_Addr (const ACE_TCHAR port_number[])
+ : ACE_Addr (AF_INET, sizeof (ACE_MEM_Addr))
+{
+ ACE_TRACE ("ACE_MEM_Addr::ACE_MEM_Addr");
+ u_short pn
+ = ACE_static_cast (u_short,
+ ACE_OS::strtoul (port_number,
+ NULL,
+ 10));
+ this->initialize_local (pn);
+}
+
+ACE_MEM_Addr::ACE_MEM_Addr (u_short port_number)
+ : ACE_Addr (AF_INET, sizeof (ACE_MEM_Addr))
+{
+ ACE_TRACE ("ACE_MEM_Addr::ACE_MEM_Addr");
+ this->initialize_local (port_number);
+}
+
+int
+ACE_MEM_Addr::initialize_local (u_short port_number)
+{
+ ACE_TCHAR name[MAXHOSTNAMELEN + 1];
+ if (ACE_OS::hostname (name, MAXHOSTNAMELEN+1) == -1)
+ return -1;
+
+ this->external_.set (port_number, name);
+ this->internal_.set (port_number, ACE_LIB_TEXT ("localhost"));
+ return 0;
+}
+
+int
+ACE_MEM_Addr::same_host (const ACE_INET_Addr &sap)
+{
+ ACE_TRACE ("ACE_MEM_Addr::same_host");
+
+ // Rather than try to obtain and compare low-level binary
+ // data, get copies of both addresses, set the ports to 0
+ // (don't care about them) then compare for equality.
+ ACE_INET_Addr me (this->external_);
+ ACE_INET_Addr you (sap);
+ me.set_port_number (0, 0); // No need to encode a 0
+ you.set_port_number (0, 0);
+ return me == you;
+}
+
+int
+ACE_MEM_Addr::addr_to_string (ACE_TCHAR s[],
+ size_t size,
+ int ipaddr_format) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::addr_to_string");
+
+ return this->external_.addr_to_string (s, size, ipaddr_format);
+}
+
+// Transform the string into the current addressing format.
+
+int
+ACE_MEM_Addr::string_to_addr (const ACE_TCHAR s[])
+{
+ ACE_TRACE ("ACE_MEM_Addr::string_to_addr");
+
+ u_short pn
+ = ACE_static_cast (u_short,
+ ACE_OS::strtoul (s,
+ NULL,
+ 10));
+ return this->set (pn);
+}
+
+// Return the address.
+
+void *
+ACE_MEM_Addr::get_addr (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_addr");
+ return this->external_.get_addr ();
+}
+
+// Set a pointer to the address.
+void
+ACE_MEM_Addr::set_addr (void *addr, int len)
+{
+ ACE_TRACE ("ACE_MEM_Addr::set_addr");
+
+ this->external_.set_addr (addr, len);
+ this->internal_.set_port_number (this->external_.get_port_number ());
+}
+
+int
+ACE_MEM_Addr::get_host_name (ACE_TCHAR hostname[],
+ size_t len) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_host_name");
+ return this->external_.get_host_name (hostname, len);
+}
+
+// Return the character representation of the hostname.
+
+const char *
+ACE_MEM_Addr::get_host_name (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_host_name");
+ return this->external_.get_host_name ();
+}
+
+void
+ACE_MEM_Addr::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->external_.dump ();
+ this->internal_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_Addr.h b/ace/Memory/MEM_Addr.h
new file mode 100644
index 00000000000..d13aa45479c
--- /dev/null
+++ b/ace/Memory/MEM_Addr.h
@@ -0,0 +1,153 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_Addr.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_ADDR_H
+#define ACE_MEM_ADDR_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/INET_Addr.h"
+
+/**
+ * @class ACE_MEM_Addr
+ *
+ * @brief Defines a C++ wrapper facade for the shared memory transport
+ * address family format.
+ */
+class ACE_Export ACE_MEM_Addr : public ACE_Addr
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_MEM_Addr (void);
+
+ /// Copy constructor.
+ ACE_MEM_Addr (const ACE_MEM_Addr &);
+
+ /// Creates an <ACE_INET_Addr> from a <port_number> and the remote
+ /// <host_name>.
+ ACE_MEM_Addr (u_short port_number);
+
+ /// Creates an <ACE_INET_Addr> from a <port_name>.
+ ACE_EXPLICIT ACE_MEM_Addr (const ACE_TCHAR port_name[]);
+
+ /// Default dtor.
+ ~ACE_MEM_Addr (void);
+
+ // = Direct initialization methods.
+
+ /// default initialization routine.
+ int initialize_local (u_short port);
+
+ /// Check if <sap> designate an enpoint withing the same host.
+ int same_host (const ACE_INET_Addr& sap);
+
+ // These methods are useful after the object has been constructed.
+
+ /**
+ * Initializes an <ACE_INET_Addr> from a <port_number> and the
+ * remote <host_name>. If <encode> is enabled then <port_number> is
+ * converted into network byte order, otherwise it is assumed to be
+ * in network byte order already and are passed straight through.
+ */
+ int set (u_short port_number,
+ int encode = 1);
+
+ /// Uses <getservbyname> to initialize an <ACE_INET_Addr> from a
+ /// <port_name>, the remote <host_name>, and the <protocol>.
+ int set (const ACE_TCHAR port_name[]);
+
+ /// Return a pointer to the underlying network address.
+ virtual void *get_addr (void) const;
+
+ /// Set a pointer to the address.
+ virtual void set_addr (void *, int len);
+
+ /// Transform the external <ACE_INET_Addr> address into string
+ /// format.
+ virtual int addr_to_string (ACE_TCHAR buffer[],
+ size_t size,
+ int ipaddr_format = 1) const;
+
+ /// Initializes the external <ACE_INET_Addr> from the <address>.
+ virtual int string_to_addr (const ACE_TCHAR address[]);
+
+ /// Sets the port number.
+ void set_port_number (u_short,
+ int encode = 1);
+
+ /// Return the port number, converting it into host byte order.
+ u_short get_port_number (void) const;
+
+ /// Return the character representation of the hostname.
+ int get_host_name (ACE_TCHAR hostname[],
+ size_t hostnamelen) const;
+
+ /**
+ * Return the character representation of the hostname (this version
+ * is non-reentrant since it returns a pointer to a static data
+ * area).
+ */
+ const char *get_host_name (void) const;
+
+ /// Return the "dotted decimal" external address.
+ const char *get_host_addr (void) const;
+
+ /// Return the 4-byte external IP address, converting it into host byte
+ /// order.
+ ACE_UINT32 get_ip_address (void) const;
+
+ const ACE_INET_Addr &get_remote_addr (void) const;
+ const ACE_INET_Addr &get_local_addr (void) const;
+
+ /// Compare two addresses for equality. The addresses are considered
+ /// equal if they contain the same IP address and port number.
+ int operator == (const ACE_MEM_Addr &SAP) const;
+ int operator == (const ACE_INET_Addr &SAP) const;
+
+ /// Compare two addresses for inequality.
+ int operator != (const ACE_MEM_Addr &SAP) const;
+ int operator != (const ACE_INET_Addr &SAP) const;
+
+ /// Computes and returns hash value.
+ virtual u_long hash (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// External INET addr used for identifying host.
+ ACE_INET_Addr external_;
+
+ /// Internal INET addr for accepting/connecting.
+ ACE_INET_Addr internal_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/MEM_Addr.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_MEM_ADDR_H */
diff --git a/ace/Memory/MEM_Addr.i b/ace/Memory/MEM_Addr.i
new file mode 100644
index 00000000000..e2cb980a34b
--- /dev/null
+++ b/ace/Memory/MEM_Addr.i
@@ -0,0 +1,117 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_Addr.i
+
+// Default dtor.
+ACE_INLINE
+ACE_MEM_Addr::~ACE_MEM_Addr (void)
+{
+}
+
+// Set the port number.
+
+ACE_INLINE void
+ACE_MEM_Addr::set_port_number (u_short port_number,
+ int encode)
+{
+ ACE_TRACE ("ACE_MEM_Addr::set_port_number");
+
+ this->external_.set_port_number (port_number, encode);
+ this->internal_.set_port_number (port_number, encode);
+}
+
+ACE_INLINE int
+ACE_MEM_Addr::set (u_short port_number, int encode)
+{
+ ACE_TRACE ("ACE_MEM_Addr::set");
+ this->set_port_number (port_number, encode);
+ return 0;
+}
+
+ACE_INLINE int
+ACE_MEM_Addr::set (const ACE_TCHAR port_number[])
+{
+ ACE_TRACE ("ACE_MEM_Addr::set");
+ return this->string_to_addr (port_number);
+}
+
+// Return the port number.
+
+ACE_INLINE u_short
+ACE_MEM_Addr::get_port_number (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_port_number");
+ return this->internal_.get_port_number ();
+}
+
+// Return the dotted Internet address.
+
+ACE_INLINE const char *
+ACE_MEM_Addr::get_host_addr (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_host_addr");
+ return this->internal_.get_host_addr ();
+}
+
+// Return the 4-byte IP address, converting it into host byte order.
+
+ACE_INLINE ACE_UINT32
+ACE_MEM_Addr::get_ip_address (void) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::get_ip_address");
+ return this->external_.get_ip_address ();
+}
+
+ACE_INLINE const ACE_INET_Addr &
+ACE_MEM_Addr::get_local_addr (void) const
+{
+ return this->internal_;
+}
+
+ACE_INLINE const ACE_INET_Addr &
+ACE_MEM_Addr::get_remote_addr (void) const
+{
+ return this->external_;
+}
+
+// Compare two addresses for equality.
+
+ACE_INLINE int
+ACE_MEM_Addr::operator == (const ACE_MEM_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator ==");
+
+ return this->external_ == sap.external_ &&
+ this->internal_ == sap.internal_;
+}
+
+ACE_INLINE int
+ACE_MEM_Addr::operator == (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator ==");
+
+ return this->external_ == sap;
+}
+
+// Compare two addresses for inequality.
+
+ACE_INLINE int
+ACE_MEM_Addr::operator != (const ACE_MEM_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+ACE_INLINE int
+ACE_MEM_Addr::operator != (const ACE_INET_Addr &sap) const
+{
+ ACE_TRACE ("ACE_MEM_Addr::operator !=");
+ return !((*this) == sap);
+}
+
+ACE_INLINE u_long
+ACE_MEM_Addr::hash (void) const
+{
+ return this->external_.hash ();
+}
diff --git a/ace/Memory/MEM_Connector.cpp b/ace/Memory/MEM_Connector.cpp
new file mode 100644
index 00000000000..617c479e978
--- /dev/null
+++ b/ace/Memory/MEM_Connector.cpp
@@ -0,0 +1,143 @@
+// MEM_Connector.cpp
+// $Id$
+
+#include "ace/MEM_Connector.h"
+
+ACE_RCSID(ace, MEM_Connector, "$Id$")
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Connector.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Connector)
+
+void
+ACE_MEM_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_MEM_Connector::ACE_MEM_Connector (void)
+ : malloc_options_ (ACE_DEFAULT_BASE_ADDR, 0),
+ preferred_strategy_ (ACE_MEM_IO::Reactive)
+{
+ ACE_TRACE ("ACE_MEM_Connector::ACE_MEM_Connector");
+}
+
+// Establish a connection.
+ACE_MEM_Connector::ACE_MEM_Connector (ACE_MEM_Stream &new_stream,
+ const ACE_INET_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol)
+ : malloc_options_ (ACE_DEFAULT_BASE_ADDR, 0),
+ preferred_strategy_ (ACE_MEM_IO::Reactive)
+{
+ ACE_TRACE ("ACE_MEM_Connector::ACE_MEM_Connector");
+ // This is necessary due to the weird inheritance relationships of
+ // ACE_MEM_Stream.
+ this->connect (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol);
+}
+
+int
+ACE_MEM_Connector::connect (ACE_MEM_Stream &new_stream,
+ const ACE_INET_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol)
+{
+ ACE_TRACE ("ACE_MEM_Connector::connect");
+
+ if (!this->address_.same_host (remote_sap))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) MEM_Connector can't connect ")
+ ACE_LIB_TEXT ("to %s:%d which is not a local endpoint"),
+ remote_sap.get_host_name (),
+ remote_sap.get_port_number ()),
+ -1);
+ else
+ this->address_.set_port_number (remote_sap.get_port_number ());
+
+
+ ACE_SOCK_Stream temp_stream;
+
+ if (ACE_SOCK_Connector::connect (temp_stream,
+ this->address_.get_local_addr (),
+ timeout, local_sap,
+ reuse_addr, flags, perms,
+ 0, protocol) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_MEM_Connector::connect")),
+ -1);
+
+
+ ACE_HANDLE new_handle = temp_stream.get_handle ();
+ new_stream.set_handle (new_handle);
+ new_stream.disable (ACE_NONBLOCK);
+ // Do not close the handle.
+
+ // now we should setup the mmap malloc.
+ ACE_TCHAR buf[MAXPATHLEN];
+
+ // @@ Need to handle timeout here.
+ ACE_INT16 server_strategy = ACE_MEM_IO::Reactive;
+ // Receive the signaling strategy theserver support.
+ if (ACE::recv (new_handle, &server_strategy,
+ sizeof (ACE_INT16)) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Connector::connect error receiving strategy\n")),
+ -1);
+
+ // If either side don't support MT, we will not use it.
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+ if (! (this->preferred_strategy_ == ACE_MEM_IO::MT &&
+ server_strategy == ACE_MEM_IO::MT))
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+ server_strategy = ACE_MEM_IO::Reactive;
+
+ if (ACE::send (new_handle, &server_strategy,
+ sizeof (ACE_INT16)) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Connector::connect error sending strategy\n")),
+ -1);
+
+ ACE_INT16 buf_len;
+ // Byte-order is not a problem for this read.
+ if (ACE::recv (new_handle, &buf_len, sizeof (buf_len)) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Connector::connect error receiving shm filename length\n")),
+ -1);
+
+ if (ACE::recv (new_handle, buf, buf_len) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_MEM_Connector::connect error receiving shm filename.\n")),
+ -1);
+
+ if (new_stream.init (buf, ACE_static_cast (ACE_MEM_IO::Signal_Strategy, server_strategy),
+ &this->malloc_options_) == -1)
+ return -1;
+
+ return 0;
+}
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_Connector.h b/ace/Memory/MEM_Connector.h
new file mode 100644
index 00000000000..900619bd539
--- /dev/null
+++ b/ace/Memory/MEM_Connector.h
@@ -0,0 +1,125 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_Connector.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MEM_CONNECTOR_H
+#define ACE_MEM_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Connector.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/MEM_Stream.h"
+#include "ace/MEM_Addr.h"
+
+/**
+ * @class ACE_MEM_Connector
+ *
+ * @brief Defines the format and interface for the connector side of
+ * the <ACE_MEM_Stream>.
+ */
+class ACE_Export ACE_MEM_Connector : public ACE_SOCK_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_MEM_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <0> then the user is letting the OS do the
+ * binding. If <reuse_addr> == 1 then the <local_addr> is reused,
+ * even if it hasn't been cleanedup yet.
+ */
+ ACE_MEM_Connector (ACE_MEM_Stream &new_stream,
+ const ACE_INET_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <0> then the user is letting the OS do the
+ * binding. If <reuse_addr> == 1 then the <local_addr> is reused,
+ * even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_MEM_Stream &new_stream,
+ const ACE_INET_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol = 0);
+
+ // Set/get the preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy (void) const;
+ void preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy);
+
+ /// Accessor to underlying malloc options.
+ ACE_MEM_SAP::MALLOC_OPTIONS &malloc_options (void);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+ typedef ACE_MEM_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// The acceptor address this connector is connecting to.
+ ACE_MEM_Addr address_;
+
+ /// A cached MALLOC_OPTIONS that the MEM_Connector used to initialize
+ /// the shared memory malloc update connection establishment.
+ ACE_MEM_SAP::MALLOC_OPTIONS malloc_options_;
+
+ // Preferred signaling strategy.
+ ACE_MEM_IO::Signal_Strategy preferred_strategy_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Connector.i"
+#endif
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_MEM_CONNECTOR_H */
diff --git a/ace/Memory/MEM_Connector.i b/ace/Memory/MEM_Connector.i
new file mode 100644
index 00000000000..09e311d76a2
--- /dev/null
+++ b/ace/Memory/MEM_Connector.i
@@ -0,0 +1,24 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_Connector.i
+
+// Establish a connection.
+
+ASYS_INLINE ACE_MEM_IO::Signal_Strategy
+ACE_MEM_Connector::preferred_strategy (void) const
+{
+ return this->preferred_strategy_;
+}
+
+ASYS_INLINE void
+ACE_MEM_Connector::preferred_strategy (ACE_MEM_IO::Signal_Strategy strategy)
+{
+ this->preferred_strategy_ = strategy;
+}
+
+ASYS_INLINE ACE_MEM_SAP::MALLOC_OPTIONS &
+ACE_MEM_Connector::malloc_options (void)
+{
+ return this->malloc_options_;
+}
diff --git a/ace/Memory/MEM_IO.cpp b/ace/Memory/MEM_IO.cpp
new file mode 100644
index 00000000000..65f5b439943
--- /dev/null
+++ b/ace/Memory/MEM_IO.cpp
@@ -0,0 +1,536 @@
+// MEM_IO.cpp
+// $Id$
+
+#include "ace/MEM_IO.h"
+#include "ace/Handle_Set.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_IO.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, MEM_IO, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_IO)
+
+ACE_Reactive_MEM_IO::~ACE_Reactive_MEM_IO ()
+{
+}
+
+int
+ACE_Reactive_MEM_IO::init (ACE_HANDLE handle,
+ const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options)
+{
+ ACE_TRACE ("ACE_Reactive_MEM_IO::init");
+ this->handle_ = handle;
+ return this->create_shm_malloc (name,
+ options);
+}
+
+int
+ACE_Reactive_MEM_IO::recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Reactive_MEM_IO::recv_buf");
+
+ if (this->shm_malloc_ == 0)
+ return -1;
+
+ off_t new_offset = 0;
+ int retv = ACE::recv (this->handle_,
+ (char *) &new_offset,
+ sizeof (off_t),
+ flags,
+ timeout);
+
+ if (retv == 0)
+ return 0;
+ else if (retv != sizeof (off_t))
+ {
+ // Nothing available or we are really screwed.
+ buf = 0;
+ return -1;
+ }
+ else
+ return this->get_buf_len (new_offset, buf);
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_Reactive_MEM_IO::send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_Reactive_MEM_IO::send_buf");
+
+ if (this->shm_malloc_ == 0)
+ return -1;
+
+ off_t offset = ACE_reinterpret_cast (char *, buf) -
+ ACE_static_cast (char *, this->shm_malloc_->base_addr ());
+ // the offset.
+ // Send the offset value over the socket.
+ if (ACE::send (this->handle_,
+ (const char *) &offset,
+ sizeof (offset),
+ flags,
+ timeout) != sizeof (offset))
+ {
+ // unsucessful send, release the memory in the shared-memory.
+ this->release_buffer (buf);
+
+ return -1;
+ }
+ return buf->size ();
+}
+
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+int
+ACE_MT_MEM_IO::Simple_Queue::write (ACE_MEM_SAP_Node *new_node)
+{
+ if (this->mq_ == 0)
+ return -1;
+
+ // Here, we assume we already have acquired the lock necessary.
+ // And we are allowed to write.
+ if (this->mq_->tail_.addr () == 0) // nothing in the queue.
+ {
+ this->mq_->head_ = new_node;
+ this->mq_->tail_ = new_node;
+ new_node->next_ = 0;
+ }
+ else
+ {
+ this->mq_->tail_->next_ = new_node;
+ new_node->next_ = 0;
+ this->mq_->tail_ = new_node;
+ }
+ return 0;
+}
+
+ACE_MEM_SAP_Node *
+ACE_MT_MEM_IO::Simple_Queue::read ()
+{
+ if (this->mq_ == 0)
+ return 0;
+
+ ACE_MEM_SAP_Node *retv = 0;
+
+ ACE_SEH_TRY
+ {
+ retv = this->mq_->head_;
+ // Here, we assume we already have acquired the lock necessary
+ // and there are soemthing in the queue.
+ if (this->mq_->head_ == this->mq_->tail_)
+ {
+ // Last message in the queue.
+ this->mq_->head_ = 0;
+ this->mq_->tail_ = 0;
+ }
+ else
+ this->mq_->head_ = retv->next_;
+ }
+ ACE_SEH_EXCEPT (this->malloc_->memory_pool ().seh_selector (GetExceptionInformation ()))
+ {
+ }
+
+ return retv;
+}
+
+ACE_MT_MEM_IO::~ACE_MT_MEM_IO ()
+{
+ delete this->recv_channel_.sema_;
+ delete this->recv_channel_.lock_;
+ delete this->send_channel_.sema_;
+ delete this->send_channel_.lock_;
+}
+
+int
+ACE_MT_MEM_IO::init (ACE_HANDLE handle,
+ const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options)
+{
+ ACE_TRACE ("ACE_MT_MEM_IO::init");
+ ACE_UNUSED_ARG (handle);
+
+ // @@ Give me a rule on naming and how the queue should
+ // be kept in the shared memory and we are done
+ // with this.
+ if (this->create_shm_malloc (name, options) == -1)
+ return -1;
+
+ ACE_TCHAR server_sema [MAXPATHLEN];
+ ACE_TCHAR client_sema [MAXPATHLEN];
+ ACE_TCHAR server_lock [MAXPATHLEN];
+ ACE_TCHAR client_lock [MAXPATHLEN];
+ const ACE_TCHAR *basename = ACE::basename (name);
+ // size_t baselen = ACE_OS::strlen (basename);
+
+ // Building names. @@ Check buffer overflow?
+ ACE_OS::strcpy (server_sema, basename);
+ ACE_OS::strcat (server_sema, ACE_LIB_TEXT ("_sema_to_server"));
+ ACE_OS::strcpy (client_sema, basename);
+ ACE_OS::strcat (client_sema, ACE_LIB_TEXT ("_sema_to_client"));
+ ACE_OS::strcpy (server_lock, basename);
+ ACE_OS::strcat (server_lock, ACE_LIB_TEXT ("_lock_to_server"));
+ ACE_OS::strcpy (client_lock, basename);
+ ACE_OS::strcat (client_lock, ACE_LIB_TEXT ("_lock_to_client"));
+
+ void *to_server_ptr = 0;
+ // @@ Here, we assume the shared memory fill will never be resued.
+ // So we can determine whether we are server or client by examining
+ // if the simple message queues have already been set up in
+ // the Malloc object or not.
+ if (this->shm_malloc_->find ("to_server", to_server_ptr) == -1)
+ {
+ void *ptr = 0;
+ // We are server.
+ ACE_ALLOCATOR_RETURN (ptr,
+ this->shm_malloc_->malloc (2 * sizeof (MQ_Struct)),
+ -1);
+
+ MQ_Struct *mymq = ACE_reinterpret_cast (MQ_Struct *, ptr);
+ mymq->tail_ = 0;
+ mymq->head_ = 0;
+ (mymq + 1)->tail_ = 0;
+ (mymq + 1)->head_ = 0;
+ if (this->shm_malloc_->bind ("to_server", mymq) == -1)
+ return -1;
+
+ if (this->shm_malloc_->bind ("to_client", mymq + 1) == -1)
+ return -1;
+
+ this->recv_channel_.queue_.init (mymq, this->shm_malloc_);
+ ACE_NEW_RETURN (this->recv_channel_.sema_,
+ ACE_SYNCH_PROCESS_SEMAPHORE (0, server_sema),
+ -1);
+ ACE_NEW_RETURN (this->recv_channel_.lock_,
+ ACE_SYNCH_PROCESS_MUTEX (server_lock),
+ -1);
+
+ this->send_channel_.queue_.init (mymq + 1, this->shm_malloc_);
+ ACE_NEW_RETURN (this->send_channel_.sema_,
+ ACE_SYNCH_PROCESS_SEMAPHORE (0, client_sema),
+ -1);
+ ACE_NEW_RETURN (this->send_channel_.lock_,
+ ACE_SYNCH_PROCESS_MUTEX (client_lock),
+ -1);
+ }
+ else
+ {
+ // we are client.
+ MQ_Struct *mymq = ACE_reinterpret_cast (MQ_Struct *, to_server_ptr);
+ this->recv_channel_.queue_.init (mymq +1, this->shm_malloc_);
+ ACE_NEW_RETURN (this->recv_channel_.sema_,
+ ACE_SYNCH_PROCESS_SEMAPHORE (0, client_sema),
+ -1);
+ ACE_NEW_RETURN (this->recv_channel_.lock_,
+ ACE_SYNCH_PROCESS_MUTEX (client_lock),
+ -1);
+
+ this->send_channel_.queue_.init (mymq, this->shm_malloc_);
+ ACE_NEW_RETURN (this->send_channel_.sema_,
+ ACE_SYNCH_PROCESS_SEMAPHORE (0, server_sema),
+ -1);
+ ACE_NEW_RETURN (this->send_channel_.lock_,
+ ACE_SYNCH_PROCESS_MUTEX (server_lock),
+ -1);
+ }
+ return 0;
+}
+
+int
+ACE_MT_MEM_IO::recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MT_MEM_IO::recv_buf");
+
+ // @@ Don't know how to handle timeout yet.
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (flags);
+
+ if (this->shm_malloc_ == 0)
+ return -1;
+
+ // Need to handle timeout here.
+ if (this->recv_channel_.sema_->acquire () == -1)
+ return -1;
+
+ {
+ // @@ We can probably skip the lock in certain circumstance.
+ ACE_GUARD_RETURN (ACE_SYNCH_PROCESS_MUTEX, ace_mon, *this->recv_channel_.lock_, -1);
+
+ buf = this->recv_channel_.queue_.read ();
+ if (buf != 0)
+ return buf->size ();
+ return -1;
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_MT_MEM_IO::send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MT_MEM_IO::send_buf");
+
+ // @@ Don't know how to handle timeout yet.
+ ACE_UNUSED_ARG (timeout);
+ ACE_UNUSED_ARG (flags);
+
+ if (this->shm_malloc_ == 0)
+ return -1;
+
+ {
+ // @@ We can probably skip the lock in certain curcumstances.
+ ACE_GUARD_RETURN (ACE_SYNCH_PROCESS_MUTEX, ace_mon, *this->send_channel_.lock_, -1);
+
+ if (this->send_channel_.queue_.write (buf) == -1)
+ {
+ this->release_buffer (buf);
+ return -1;
+ }
+ }
+
+ if (this->send_channel_.sema_->release () == -1)
+ return -1;
+
+ return buf->size ();
+}
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+
+void
+ACE_MEM_IO::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_IO::dump");
+}
+
+int
+ACE_MEM_IO::init (const ACE_TCHAR *name,
+ ACE_MEM_IO::Signal_Strategy type,
+ ACE_MEM_SAP::MALLOC_OPTIONS *options)
+{
+ ACE_UNUSED_ARG (type);
+
+ delete this->deliver_strategy_;
+ this->deliver_strategy_ = 0;
+ switch (type)
+ {
+ case ACE_MEM_IO::Reactive:
+ ACE_NEW_RETURN (this->deliver_strategy_,
+ ACE_Reactive_MEM_IO (),
+ -1);
+ break;
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+ case ACE_MEM_IO::MT:
+ ACE_NEW_RETURN (this->deliver_strategy_,
+ ACE_MT_MEM_IO (),
+ -1);
+ break;
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+ default:
+ return -1;
+ }
+
+ return this->deliver_strategy_->init (this->get_handle (),
+ name,
+ options);
+}
+
+int
+ACE_MEM_IO::fini ()
+{
+ if (this->deliver_strategy_ != 0)
+ return this->deliver_strategy_->fini ();
+ else
+ return -1;
+}
+
+// Allows a client to read from a socket without having to provide
+// a buffer to read. This method determines how much data is in the
+// socket, allocates a buffer of this size, reads in the data, and
+// returns the number of bytes read.
+
+ssize_t
+ACE_MEM_IO::send (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+
+ if (this->deliver_strategy_ == 0)
+ return -1; // Something went seriously wrong.
+
+ ssize_t len = message_block->total_length ();
+
+ if (len != 0)
+ {
+ ACE_MEM_SAP_Node *buf =
+ ACE_reinterpret_cast (ACE_MEM_SAP_Node *,
+ this->deliver_strategy_->acquire_buffer (len));
+ ssize_t n = 0;
+ while (message_block != 0)
+ {
+ ACE_OS::memcpy (ACE_static_cast (char *, buf->data ()) + n,
+ message_block->rd_ptr (),
+ message_block->length ());
+ n += message_block->length ();
+
+ if (message_block->cont ())
+ message_block = message_block->cont ();
+ else
+ message_block = message_block->next ();
+ }
+
+ buf->size_ = len;
+
+ return this->deliver_strategy_->send_buf (buf,
+ 0,
+ timeout);
+ }
+ return 0;
+}
+
+
+#if 0
+ssize_t
+ACE_MEM_IO::recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::recvv");
+#if defined (FIONREAD)
+ ACE_Handle_Set handle_set;
+ handle_set.reset ();
+ handle_set.set_bit (this->get_handle ());
+
+ io_vec->iov_base = 0;
+
+ // Check the status of the current socket.
+ switch (ACE_OS::select (int (this->get_handle ()) + 1,
+ handle_set,
+ 0, 0,
+ timeout))
+ {
+ case -1:
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ errno = ETIME;
+ return -1;
+ /* NOTREACHED */
+ default:
+ // Goes fine, fallthrough to get data
+ break;
+ }
+
+ u_long inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ (u_long *) &inlen) == -1)
+ return -1;
+ else if (inlen > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[inlen],
+ -1);
+ io_vec->iov_len = this->recv (io_vec->iov_base,
+ inlen);
+ return io_vec->iov_len;
+ }
+ else
+ return 0;
+#else
+ ACE_UNUSED_ARG (io_vec);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* FIONREAD */
+}
+
+// Send N char *ptrs and int lengths. Note that the char *'s precede
+// the ints (basically, an varargs version of writev). The count N is
+// the *total* number of trailing arguments, *not* a couple of the
+// number of tuple pairs!
+
+ssize_t
+ACE_MEM_IO::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, ssize_t);
+ }
+
+ ssize_t result = ACE_OS::sendv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// This is basically an interface to ACE_OS::readv, that doesn't use
+// the struct iovec_Base explicitly. The ... can be passed as an arbitrary
+// number of (char *ptr, int len) tuples. However, the count N is the
+// *total* number of trailing arguments, *not* a couple of the number
+// of tuple pairs!
+
+ssize_t
+ACE_MEM_IO::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, ssize_t);
+ }
+
+ ssize_t result = ACE_OS::recvv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+#endif /* 0 */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_IO.h b/ace/Memory/MEM_IO.h
new file mode 100644
index 00000000000..101f41e6256
--- /dev/null
+++ b/ace/Memory/MEM_IO.h
@@ -0,0 +1,301 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_IO.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_IO_H
+#define ACE_MEM_IO_H
+#include "ace/pre.h"
+
+#include "ace/SOCK.h"
+#include "ace/MEM_SAP.h"
+#include "ace/Memory_Pool.h"
+#include "ace/Message_Block.h"
+#include "ace/Process_Semaphore.h"
+#include "ace/Process_Mutex.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+class ACE_Export ACE_Reactive_MEM_IO : public ACE_MEM_SAP
+{
+public:
+ ACE_Reactive_MEM_IO (void);
+
+ virtual ~ACE_Reactive_MEM_IO (void);
+
+ /**
+ * Initialize the MEM_SAP object.
+ */
+ virtual int init (ACE_HANDLE handle,
+ const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options);
+
+ /**
+ * Fetch location of next available data into <recv_buffer_>.
+ * As this operation read the address of the data off the socket
+ * using ACE::recv, <timeout> only applies to ACE::recv.
+ */
+ virtual int recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to <timeout> amount of time to send <buf>. If <send>
+ * times out a -1 is returned with <errno == ETIME>. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual int send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Convert the buffer offset <off> to absolute address to <buf>.
+ * Return the size of valid information containing in the <buf>,
+ * -1 if <shm_malloc_> is not initialized.
+ */
+ ssize_t get_buf_len (const off_t off, ACE_MEM_SAP_Node *&buf);
+};
+
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+class ACE_Export ACE_MT_MEM_IO : public ACE_MEM_SAP
+{
+public:
+ typedef struct
+ {
+ ACE_MEM_SAP_Node::ACE_MEM_SAP_NODE_PTR head_;
+ ACE_MEM_SAP_Node::ACE_MEM_SAP_NODE_PTR tail_;
+ } MQ_Struct; // Structure for a simple queue
+
+ class Simple_Queue
+ {
+ public:
+ ACE_INLINE_FOR_GNUC Simple_Queue (void);
+ Simple_Queue (MQ_Struct *mq);
+
+ int init (MQ_Struct *mq, ACE_MEM_SAP::MALLOC_TYPE *malloc);
+
+ int write (ACE_MEM_SAP_Node *new_msg);
+
+ ACE_MEM_SAP_Node *read (void);
+ private:
+ MQ_Struct *mq_;
+ ACE_MEM_SAP::MALLOC_TYPE *malloc_;
+ };
+
+ typedef struct
+ {
+ ACE_SYNCH_PROCESS_SEMAPHORE *sema_;
+ ACE_SYNCH_PROCESS_MUTEX *lock_;
+ Simple_Queue queue_;
+ } Channel;
+
+ ACE_MT_MEM_IO (void);
+
+ virtual ~ACE_MT_MEM_IO (void);
+
+ /**
+ * Initialize the MEM_SAP object.
+ */
+ virtual int init (ACE_HANDLE handle,
+ const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options);
+
+ /**
+ * Fetch location of next available data into <recv_buffer_>.
+ * As this operation read the address of the data off the socket
+ * using ACE::recv, <timeout> only applies to ACE::recv.
+ */
+ virtual int recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to <timeout> amount of time to send <buf>. If <send>
+ * times out a -1 is returned with <errno == ETIME>. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual int send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+private:
+ Channel recv_channel_;
+ Channel send_channel_;
+};
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+
+/**
+ * @class ACE_MEM_IO
+ *
+ * @brief Defines the methods for the ACE shared memeory wrapper I/O
+ * routines (e.g., send/recv).
+ * The shared memory transport uses ACE_SOCK_* class to
+ * implement the signaling mechanism so we can easily use the
+ * new mechanism with the Reactor pattern (which uses select
+ * under the hood.)
+ * ACE_MEM_Acceptor and ACE_MEM_Connector are used to establish
+ * connections. When a connection is established,
+ * ACE_MEM_Acceptor creates the MMAP file for data exchange and
+ * sends the location of the file (complete path name) to
+ * ACE_MEM_Connector thru the socket. ACE_MEM_Connector then
+ * reads the location of the file off the socket and opens up
+ * the same MMAP file. ACE_MEM_Stream at each side then
+ * contains a reference to the ACE_Mallo object using the same
+ * MMAP file.
+ * When sending information using methods provided in this
+ * class, ACE_MEM_IO requests a chunk of memory from the
+ * MALLOC_TYPE object, copy the data into the shared memory and
+ * send the memory offset (from the start of the ACE_Malloc)
+ * across the socket. This action also servers as a signal to
+ * the other end. The receiving side then reverses the
+ * procedures and copies the information into user buffer.
+ */
+class ACE_Export ACE_MEM_IO : public ACE_SOCK
+{
+public:
+ // = Initialization and termination methods.
+ /// Constructor.
+ ACE_MEM_IO (void);
+
+ /// Destructor.
+ ~ACE_MEM_IO (void);
+
+ typedef enum
+ {
+ Reactive,
+ MT
+ } Signal_Strategy;
+
+ /**
+ * Initialize the MEM_SAP object.
+ */
+ int init (const ACE_TCHAR *name,
+ ACE_MEM_IO::Signal_Strategy type = ACE_MEM_IO::Reactive,
+ ACE_MEM_SAP::MALLOC_OPTIONS *options = 0);
+
+ /**
+ * Finalizing the MEM_IO object. This method doesn't invoke
+ * the <remove> method.
+ */
+ int fini (void);
+
+ /// Send an <n> byte buffer to the other process using shm_malloc_
+ /// connected thru the socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags) ;
+
+ /// Recv an <n> byte buffer from the shm_malloc_ thru connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags) ;
+
+ /// Send an <n> byte buffer to the other process using shm_malloc_
+ /// connected thru the socket.
+ ssize_t send (const void *buf,
+ size_t n) ;
+
+ /// Recv an <n> byte buffer from the shm_malloc_ thru connected socket.
+ ssize_t recv (void *buf,
+ size_t n) ;
+
+ /**
+ * Wait to to <timeout> amount of time to send up to <n> bytes into
+ * <buf> from <handle> (uses the <send> call). If <send> times out
+ * a -1 is returned with <errno == ETIME>. If it succeeds the
+ * number of bytes sent is returned.
+ */
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to <timeout> amount of time to send up to <n> bytes into
+ * <buf> from <handle> (uses the <send> call). If <send> times out
+ * a -1 is returned with <errno == ETIME>. If it succeeds the
+ * number of bytes sent is returned.
+ */
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait to to <timeout> amount of time to send the <message_block>.
+ * If <send> times out a -1 is returned with <errno == ETIME>. If
+ * it succeeds the number of bytes sent is returned.
+ */
+ ssize_t send (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait up to <timeout> amount of time to receive up to <n> bytes
+ * into <buf> from <handle> (uses the <recv> call). If <recv> times
+ * out a -1 is returned with <errno == ETIME>. If it succeeds the
+ * number of bytes received is returned.
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Wait up to <timeout> amount of time to receive up to <n> bytes
+ * into <buf> from <handle> (uses the <recv> call). If <recv> times
+ * out a -1 is returned with <errno == ETIME>. If it succeeds the
+ * number of bytes received is returned.
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Return the local endpoint port number. Returns 0 if successful,
+ /// else -1.
+ /* int get_local_port (u_short &) const;
+
+ /// Return the port number of the remotely connected peer (if there
+ /// is one). Returns 0 if successful, else -1.
+ int get_remote_port (u_short &) const;
+ */
+
+private:
+ ssize_t fetch_recv_buf (int flag, const ACE_Time_Value *timeout);
+
+ /// Actual deliverying mechanism.
+ ACE_MEM_SAP *deliver_strategy_;
+
+ /// Internal pointer for support recv/send.
+ ACE_MEM_SAP_Node *recv_buffer_;
+
+ /// Record the current total buffer size of <recv_buffer_>.
+ ssize_t buf_size_;
+
+ /// Record the current read pointer location in <recv_buffer_>.
+ ssize_t cur_offset_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_IO.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_IO_H */
diff --git a/ace/Memory/MEM_IO.i b/ace/Memory/MEM_IO.i
new file mode 100644
index 00000000000..796121a6c6e
--- /dev/null
+++ b/ace/Memory/MEM_IO.i
@@ -0,0 +1,230 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_IO.i
+
+ASYS_INLINE
+ACE_Reactive_MEM_IO::ACE_Reactive_MEM_IO ()
+{
+}
+
+#if defined (ACE_WIN32) || !defined (_ACE_USE_SV_SEM)
+ASYS_INLINE
+ACE_MT_MEM_IO::Simple_Queue::Simple_Queue (void)
+ : mq_ (0),
+ malloc_ (0)
+{
+}
+
+ASYS_INLINE
+ACE_MT_MEM_IO::ACE_MT_MEM_IO ()
+{
+ this->recv_channel_.sema_ = 0;
+ this->recv_channel_.lock_ = 0;
+ this->send_channel_.sema_ = 0;
+ this->send_channel_.lock_ = 0;
+}
+
+ASYS_INLINE
+ACE_MT_MEM_IO::Simple_Queue::Simple_Queue (MQ_Struct *mq)
+ : mq_ (mq),
+ malloc_ (0)
+{
+}
+
+ASYS_INLINE int
+ACE_MT_MEM_IO::Simple_Queue::init (MQ_Struct *mq,
+ ACE_MEM_SAP::MALLOC_TYPE *malloc)
+{
+ if (this->mq_ != 0)
+ return -1;
+
+ this->mq_ = mq;
+ this->malloc_ = malloc;
+ return 0;
+}
+#endif /* ACE_WIN32 || !_ACE_USE_SV_SEM */
+
+ASYS_INLINE ssize_t
+ACE_Reactive_MEM_IO::get_buf_len (const off_t off, ACE_MEM_SAP_Node *&buf)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Reactive_MEM_IO::get_buf_len");
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (this->shm_malloc_ == 0)
+ return -1;
+
+ ssize_t retv = 0;
+
+ ACE_SEH_TRY
+ {
+ buf = ACE_reinterpret_cast (ACE_MEM_SAP_Node *,
+ (ACE_static_cast(char *,
+ this->shm_malloc_->base_addr ())
+ + off));
+ retv = buf->size ();
+ }
+ ACE_SEH_EXCEPT (this->shm_malloc_->memory_pool ().seh_selector (GetExceptionInformation ()))
+ {
+ }
+
+ return retv;
+}
+
+// Send an n byte message to the connected socket.
+ASYS_INLINE
+ACE_MEM_IO::ACE_MEM_IO (void)
+ : deliver_strategy_ (0),
+ recv_buffer_ (0),
+ buf_size_ (0),
+ cur_offset_ (0)
+{
+ // ACE_TRACE ("ACE_MEM_IO::ACE_MEM_IO");
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::fetch_recv_buf (int flag, const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::fetch_recv_buf");
+
+ if (this->deliver_strategy_ == 0)
+ return -1;
+
+ // This method can only be called when <buf_size_> == <cur_offset_>.
+ ACE_ASSERT (this->buf_size_ == this->cur_offset_);
+
+ // We have done using the previous buffer, return it to malloc.
+ if (this->recv_buffer_ != 0)
+ this->deliver_strategy_->release_buffer (this->recv_buffer_);
+
+ this->cur_offset_ = 0;
+ int retv = 0;
+
+ if ((retv = this->deliver_strategy_->recv_buf (this->recv_buffer_,
+ flag,
+ timeout)) > 0)
+ this->buf_size_ = retv;
+ else
+ this->buf_size_ = 0;
+
+ return retv;
+}
+
+ASYS_INLINE
+ACE_MEM_IO::~ACE_MEM_IO (void)
+{
+ delete this->deliver_strategy_;
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::send (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+ if (this->deliver_strategy_ == 0)
+ return 0;
+
+ ACE_MEM_SAP_Node *sbuf = this->deliver_strategy_->acquire_buffer (len);
+ if (sbuf == 0)
+ return -1; // Memory buffer not initialized.
+ ACE_OS::memcpy (sbuf->data (), buf, len);
+
+ ///
+
+ sbuf->size_ = len;
+
+ return this->deliver_strategy_->send_buf (sbuf,
+ flags,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::recv (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+
+ size_t count = 0;
+
+// while (len > 0)
+// {
+ size_t buf_len = this->buf_size_ - this->cur_offset_;
+ if (buf_len == 0)
+ {
+ ssize_t blen = // Buffer length
+ this->fetch_recv_buf (flags, timeout);
+ if (blen <= 0)
+ return blen;
+ buf_len = this->buf_size_;
+ }
+
+ size_t length = (len > buf_len ? buf_len : len);
+
+ ACE_OS::memcpy ((char *) buf + count,
+ (char *) this->recv_buffer_->data () + this->cur_offset_,
+ length);
+ this->cur_offset_ += length;
+// len -= length;
+ count += length;
+// }
+
+ return count;
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::send (const void *buf, size_t n, int flags)
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+ return this->send (buf, n, flags, 0);
+}
+
+// Recv an n byte message from the connected socket.
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::recv (void *buf, size_t n, int flags)
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+ return this->recv (buf, n, flags, 0);
+}
+
+// Send an n byte message to the connected socket.
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::send (const void *buf, size_t n)
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+ return this->send (buf, n, 0);
+}
+
+// Recv an n byte message from the connected socket.
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::recv (void *buf, size_t n)
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+
+ return this->recv (buf, n, 0);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::recv (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::recv");
+ return this->recv (buf, len, 0, timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_IO::send (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE_MEM_IO::send");
+ return this->send (buf, len, 0, timeout);
+}
diff --git a/ace/Memory/MEM_SAP.cpp b/ace/Memory/MEM_SAP.cpp
new file mode 100644
index 00000000000..3031578e046
--- /dev/null
+++ b/ace/Memory/MEM_SAP.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "ace/MEM_SAP.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_SAP.i"
+#endif
+
+ACE_RCSID(ace, MEM_SAP, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_IPC_SAP)
+
+void
+ACE_MEM_SAP::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_SAP::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ if (this->shm_malloc_ != 0)
+ this->shm_malloc_->dump ();
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_MEM_SAP uninitialized.\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_MEM_SAP::ACE_MEM_SAP (void)
+ : handle_ (ACE_INVALID_HANDLE),
+ shm_malloc_ (0)
+{
+ // ACE_TRACE ("ACE_MEM_SAP::ACE_MEM_SAP");
+}
+
+int
+ACE_MEM_SAP::fini ()
+{
+ ACE_TRACE ("ACE_MEM_SAP::fini");
+
+ return this->close_shm_malloc ();
+}
+
+int
+ACE_MEM_SAP::create_shm_malloc (const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options)
+{
+ ACE_TRACE ("ACE_MEM_SAP::create_shm_malloc");
+
+ if (this->shm_malloc_ != 0)
+ return -1; // already initialized.
+
+ ACE_NEW_RETURN (this->shm_malloc_,
+ MALLOC_TYPE (name,
+ 0,
+ options),
+ -1);
+
+ return 0;
+}
+
+int
+ACE_MEM_SAP::close_shm_malloc (void)
+{
+ ACE_TRACE ("ACE_MEM_SAP::close_shm_malloc");
+
+ int retv = -1;
+
+ if (this->shm_malloc_ != 0 && this->shm_malloc_->release () == 0)
+ retv = this->shm_malloc_->remove ();
+
+ return retv;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Write_Guard<ACE_Process_Mutex>;
+template class ACE_Read_Guard<ACE_Process_Mutex>;
+template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex, ACE_PI_Control_Block>;
+template class ACE_Based_Pointer<ACE_MEM_SAP_Node>;
+template class ACE_Based_Pointer_Basic<ACE_MEM_SAP_Node>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Write_Guard<ACE_Process_Mutex>
+#pragma instantiate ACE_Read_Guard<ACE_Process_Mutex>
+#pragma instantiate ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex, ACE_PI_Control_Block>
+#pragma instantiate ACE_Based_Pointer<ACE_MEM_SAP_Node>
+#pragma instantiate ACE_Based_Pointer_Basic<ACE_MEM_SAP_Node>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_SAP.h b/ace/Memory/MEM_SAP.h
new file mode 100644
index 00000000000..f3e7f4e91f5
--- /dev/null
+++ b/ace/Memory/MEM_SAP.h
@@ -0,0 +1,161 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_SAP.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_SAP_H
+#define ACE_MEM_SAP_H
+#include "ace/pre.h"
+
+#include "ace/PI_Malloc.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// MEM_SAP requries position independent pointers to work
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/Process_Mutex.h"
+
+class ACE_MEM_SAP;
+class ACE_Reactive_MEM_IO;
+class ACE_MT_MEM_IO;
+class ACE_MEM_IO;
+
+// Internal data structure
+// MEM_SAP uses to queue up
+// data.
+class ACE_Export ACE_MEM_SAP_Node
+{
+public:
+// friend class ACE_MEM_SAP;
+// friend class ACE_Reactive_MEM_IO;
+// friend class ACE_MT_MEM_IO;
+// friend class ACE_MEM_IO;
+
+ typedef ACE_Based_Pointer<ACE_MEM_SAP_Node> ACE_MEM_SAP_NODE_PTR;
+
+ // Initialize the node with its capacity.
+ ACE_MEM_SAP_Node (size_t cap);
+
+ // Get the size of the data we hold.
+ size_t size (void) const;
+
+ // Get the capacity of this block of data.
+ size_t capacity (void) const;
+
+ // Get the pointer to the block of data we hold.
+ void *data (void);
+
+ // The maximum size of this memory block.
+ size_t capacity_;
+
+ // The actualy size used.
+ size_t size_;
+
+ ACE_MEM_SAP_NODE_PTR next_;
+};
+
+/**
+ * @Class ACE_MEM_SAP
+ *
+ * @brief Defines the methods of shared memory management for
+ * shared memory transport.
+ */
+class ACE_Export ACE_MEM_SAP
+{
+public:
+ // = Initialization and termination methods.
+
+ typedef ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex, ACE_PI_Control_Block> MALLOC_TYPE;
+ typedef ACE_MMAP_Memory_Pool_Options MALLOC_OPTIONS;
+
+ /// Destructor.
+ virtual ~ACE_MEM_SAP (void);
+
+ /**
+ * Initialize the MEM_SAP object.
+ */
+ virtual int init (ACE_HANDLE handle,
+ const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options) = 0;
+
+ /**
+ * Finalizing the MEM_SAP object. This method doesn't invoke
+ * the <remove> method.
+ */
+ virtual int fini ();
+
+ /**
+ * Fetch location of next available data into <recv_buffer_>.
+ * As this operation read the address of the data off the socket
+ * using ACE::recv, <timeout> only applies to ACE::recv.
+ */
+ virtual int recv_buf (ACE_MEM_SAP_Node *&buf,
+ int flags,
+ const ACE_Time_Value *timeout) = 0;
+
+ /**
+ * Wait to to <timeout> amount of time to send <buf>. If <send>
+ * times out a -1 is returned with <errno == ETIME>. If it succeeds
+ * the number of bytes sent is returned. */
+ virtual int send_buf (ACE_MEM_SAP_Node *buf,
+ int flags,
+ const ACE_Time_Value *timeout) = 0;
+
+ /// request a buffer of size <size>. Return 0 if the <shm_malloc_> is
+ /// not initialized.
+ ACE_MEM_SAP_Node *acquire_buffer (const ssize_t size);
+
+ /// release a buffer pointed by <buf>. Return -1 if the <shm_malloc_>
+ /// is not initialized.
+ int release_buffer (ACE_MEM_SAP_Node *buf);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Class initializing methods to create/connect to a shared memory pool.
+
+ /**
+ * Create a new shm_malloc object. Return 0 if succeed and -1
+ * otherwise. This method should only be called from an acceptor
+ * class that wants to create a new memory pool for inter process
+ * communication.
+ */
+ int create_shm_malloc (const ACE_TCHAR *name,
+ MALLOC_OPTIONS *options);
+
+ /// Close down the share memory pool. Clean up the
+ /// mmap file if we are the last one using it.
+ int close_shm_malloc (void);
+
+ ACE_HANDLE handle_;
+
+ /// Data exchange channel.
+ MALLOC_TYPE *shm_malloc_;
+
+ /// Constructor. Prevent this class from being instantiated.
+ ACE_MEM_SAP (void);
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_SAP.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_IO_H */
diff --git a/ace/Memory/MEM_SAP.i b/ace/Memory/MEM_SAP.i
new file mode 100644
index 00000000000..b6a800df06b
--- /dev/null
+++ b/ace/Memory/MEM_SAP.i
@@ -0,0 +1,67 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_SAP.i
+
+
+ASYS_INLINE
+ACE_MEM_SAP_Node::ACE_MEM_SAP_Node (size_t cap)
+ : capacity_ (cap),
+ size_ (0),
+ next_ (0)
+{
+}
+
+ASYS_INLINE size_t
+ACE_MEM_SAP_Node::size (void) const
+{
+ return this->size_;
+}
+
+ASYS_INLINE size_t
+ACE_MEM_SAP_Node::capacity (void) const
+{
+ return this->capacity_;
+}
+
+ASYS_INLINE void *
+ACE_MEM_SAP_Node::data (void)
+{
+ return this + 1;
+}
+
+ASYS_INLINE
+ACE_MEM_SAP::~ACE_MEM_SAP (void)
+{
+ // ACE_TRACE ("ACE_MEM_SAP::~ACE_MEM_SAP");
+ delete this->shm_malloc_;
+}
+
+
+ASYS_INLINE ACE_MEM_SAP_Node *
+ACE_MEM_SAP::acquire_buffer (const ssize_t size)
+{
+ ACE_TRACE ("ACE_MEM_SAP::acquire_buffer");
+ if (this->shm_malloc_ == 0)
+ return 0; // not initialized.
+
+ ACE_MEM_SAP_Node *buf = 0;
+
+ ACE_NEW_MALLOC_RETURN (buf,
+ ACE_static_cast (ACE_MEM_SAP_Node *,
+ this->shm_malloc_->malloc (sizeof (ACE_MEM_SAP_Node) + size)),
+ ACE_MEM_SAP_Node (size),
+ 0);
+ return buf;
+}
+
+ASYS_INLINE int
+ACE_MEM_SAP::release_buffer (ACE_MEM_SAP_Node *buf)
+{
+ ACE_TRACE ("ACE_MEM_SAP::release_buffer");
+ if (this->shm_malloc_ == 0)
+ return -1; // not initialized.
+
+ this->shm_malloc_->free (buf);
+ return 0;
+}
diff --git a/ace/Memory/MEM_Stream.cpp b/ace/Memory/MEM_Stream.cpp
new file mode 100644
index 00000000000..79b37e21838
--- /dev/null
+++ b/ace/Memory/MEM_Stream.cpp
@@ -0,0 +1,41 @@
+// MEM_Stream.cpp
+// $Id$
+
+#include "ace/MEM_Stream.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Stream.i"
+#endif
+
+ACE_RCSID(ace, MEM_Stream, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MEM_Stream)
+
+void
+ACE_MEM_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::dump");
+}
+
+int
+ACE_MEM_Stream::close (void)
+{
+ this->send ((char *)0, 0);
+
+ this->fini ();
+
+#if defined (ACE_WIN32)
+ // We need the following call to make things work correctly on
+ // Win32, which requires use to do a <close_writer> before doing the
+ // close in order to avoid losing data. Note that we don't need to
+ // do this on UNIX since it doesn't have this "feature". Moreover,
+ // this will cause subtle problems on UNIX due to the way that
+ // fork() works.
+ this->close_writer ();
+#endif /* ACE_WIN32 */
+ // Close down the socket.
+ return ACE_SOCK::close ();
+}
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
diff --git a/ace/Memory/MEM_Stream.h b/ace/Memory/MEM_Stream.h
new file mode 100644
index 00000000000..24cfbce2733
--- /dev/null
+++ b/ace/Memory/MEM_Stream.h
@@ -0,0 +1,142 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MEM_Stream.h
+ *
+ * $Id$
+ *
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_STREAM_H
+#define ACE_MEM_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/MEM_IO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+
+#include "ace/INET_Addr.h"
+
+class ACE_MEM_Acceptor;
+class ACE_MEM_Connector;
+
+/**
+ * @class ACE_MEM_Stream
+ *
+ * @brief Defines the methods in the <ACE_MEM_Stream> abstraction.
+ *
+ * This adds additional wrapper methods atop the <ACE_MEM_IO>
+ * class.
+ */
+class ACE_Export ACE_MEM_Stream : public ACE_MEM_IO
+{
+public:
+
+ friend class ACE_MEM_Acceptor;
+ friend class ACE_MEM_Connector;
+
+ // Initialization and termination methods.
+ /// Constructor.
+ ACE_MEM_Stream (void);
+
+ /// Constructor (sets the underlying <ACE_HANDLE> with <h>).
+ ACE_MEM_Stream (ACE_HANDLE h);
+
+ /// Destructor.
+ ~ACE_MEM_Stream (void);
+
+ //= The following two methods use write and read system calls.
+ /// Send n bytes, keep trying until n are sent.
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t send_n (const void *buf, int n);
+ ssize_t recv_n (void *buf, int n);
+
+ // = The following two methods use the send and recv system calls.
+ /// Send n bytes, keep trying until n are sent.
+ /// Recv n bytes, keep trying until n are received.
+ ssize_t send_n (const void *buf, int n, int flags);
+ ssize_t recv_n (void *buf, int n, int flags);
+
+#if 0
+ /**
+ * Try to send exactly <len> bytes into <buf> from <handle> (uses
+ * the <send> call). If <send> blocks for longer than <timeout> the
+ * number of bytes actually sent is returned with <errno == ETIME>.
+ * If a timeout does not occur, <send_n> return <len> (i.e., the
+ * number of bytes requested to be sent).
+ */
+ ssize_t send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Try to recv exactly <len> bytes into <buf> from <handle> (uses
+ * the <ACE::recv_n> call). The <ACE_Time_Value> indicates how long
+ * to blocking trying to receive. If <timeout> == 0, the caller
+ * will block until action is possible, else will wait until the
+ * relative time specified in *<timeout> elapses). If <recv> blocks
+ * for longer than <timeout> the number of bytes actually read is
+ * returned with <errno == ETIME>. If a timeout does not occur,
+ * <recv_n> return <len> (i.e., the number of bytes requested to be
+ * read).
+ */
+ ssize_t recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout);
+
+ /**
+ * Send an <iovec> of size <n> to the connected socket (uses
+ * <ACE::sendv_n>). Will block until all bytes are sent or an error
+ * occurs.
+ */
+ ssize_t sendv_n (const iovec iov[],
+ size_t n) const;
+
+ /// Receive an <iovec> of size <n> to the connected socket.
+ ssize_t recvv_n (iovec iov[],
+ size_t n) const;
+#endif /* 0 */
+
+ // = Selectively close endpoints.
+
+ /// Close down the reader.
+ int close_reader (void);
+
+ /// Close down the writer.
+ int close_writer (void);
+
+ /**
+ * Close down the socket (we need this to make things work correctly
+ * on Win32, which requires use to do a <close_writer> before doing
+ * the close to avoid losing data).
+ */
+ int close (void);
+
+ // = Meta-type info
+ typedef ACE_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/MEM_Stream.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#include "ace/post.h"
+#endif /* ACE_MEM_STREAM_H */
diff --git a/ace/Memory/MEM_Stream.i b/ace/Memory/MEM_Stream.i
new file mode 100644
index 00000000000..07f68fafdd0
--- /dev/null
+++ b/ace/Memory/MEM_Stream.i
@@ -0,0 +1,176 @@
+/* -*- C++ -*- */
+// $Id$
+
+// MEM_Stream.i
+
+#include "ace/MEM_Stream.h"
+
+ASYS_INLINE
+ACE_MEM_Stream::ACE_MEM_Stream (void)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::ACE_MEM_Stream");
+}
+
+ASYS_INLINE
+ACE_MEM_Stream::ACE_MEM_Stream (ACE_HANDLE h)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::ACE_MEM_Stream");
+ this->set_handle (h);
+}
+
+ASYS_INLINE
+ACE_MEM_Stream::~ACE_MEM_Stream (void)
+{
+ // ACE_TRACE ("ACE_MEM_Stream::~ACE_MEM_Stream");
+}
+
+ASYS_INLINE int
+ACE_MEM_Stream::close_reader (void)
+{
+ ACE_TRACE ("ACE_MEM_Stream::close_reader");
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return ACE_OS::shutdown (this->get_handle (), ACE_SHUTDOWN_READ);
+ else
+ return 0;
+}
+
+// Shut down just the writing end of a ACE_SOCK.
+
+ASYS_INLINE int
+ACE_MEM_Stream::close_writer (void)
+{
+ ACE_TRACE ("ACE_MEM_Stream::close_writer");
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return ACE_OS::shutdown (this->get_handle (), ACE_SHUTDOWN_WRITE);
+ else
+ return 0;
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf, int n)
+{
+ return this->send (buf, n);
+}
+
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf, int n)
+{
+ return this->recv (buf, n);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf, int n, int flags)
+{
+ return this->send (buf, n, flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf, int n, int flags)
+{
+ return this->recv (buf, n, flags);
+}
+
+#if 0
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recv_n (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recvv_n (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::recvv_n");
+ return ACE::recvv_n (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::send_n (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::sendv_n (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::sendv_n");
+ return ACE::sendv_n (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::send_urg (const void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::send_urg");
+ return ACE::send (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_MEM_Stream::recv_urg (void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_MEM_Stream::recv_urg");
+ return ACE::recv (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
+#endif /* 0 */
diff --git a/ace/Memory/Malloc.cpp b/ace/Memory/Malloc.cpp
new file mode 100644
index 00000000000..1033462eb48
--- /dev/null
+++ b/ace/Memory/Malloc.cpp
@@ -0,0 +1,161 @@
+// $Id$
+
+#if !defined (ACE_MALLOC_CPP)
+#define ACE_MALLOC_CPP
+
+#include "ace/Malloc.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Synch_T.h"
+
+ACE_RCSID(ace, Malloc, "$Id$")
+
+// Process-wide ACE_Allocator.
+ACE_Allocator *ACE_Allocator::allocator_ = 0;
+
+// Controls whether the Allocator is deleted when we shut down (we can
+// only delete it safely if we created it!) This is no longer used;
+// see ACE_Allocator::instance (void).
+int ACE_Allocator::delete_allocator_ = 0;
+
+void
+ACE_Control_Block::ACE_Malloc_Header::dump (void) const
+{
+ ACE_TRACE ("ACE_Control_Block::ACE_Malloc_Header::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnext_block = %x"), (ACE_Malloc_Header *) this->next_block_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_Control_Block::print_alignment_info (void)
+{
+ ACE_TRACE ("ACE_Control_Block::print_alignment_info");
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Start ---> ACE_Control_Block::print_alignment_info:\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Sizeof ptr: %d\n")
+ ACE_LIB_TEXT ("Sizeof size_t: %d\n")
+ ACE_LIB_TEXT ("Sizeof long: %d\n")
+ ACE_LIB_TEXT ("Sizeof double: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_MALLOC_ALIGN: %d\n")
+ ACE_LIB_TEXT ("sizeof ACE_MALLOC_PADDING: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_MALLOC_HEADER_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_MALLOC_PADDING_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_CONTROL_BLOCK_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_CONTROL_BLOCK_ALIGN_LONGS: %d\n")
+ ACE_LIB_TEXT ("Sizeof (MALLOC_HEADER): %d\n")
+ ACE_LIB_TEXT ("Sizeof (CONTROL_BLOCK): %d\n"),
+ sizeof (char *),
+ sizeof (size_t),
+ sizeof (long),
+ sizeof (double),
+ ACE_MALLOC_ALIGN,
+ ACE_MALLOC_PADDING,
+ ACE_MALLOC_HEADER_SIZE,
+ ACE_MALLOC_PADDING_SIZE,
+ ACE_CONTROL_BLOCK_SIZE,
+ ACE_CONTROL_BLOCK_ALIGN_LONGS,
+ sizeof (ACE_Malloc_Header),
+ sizeof (ACE_Control_Block)
+ ));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("End <--- ACE_Control_Block::print_alignment_info:\n")));
+}
+
+void
+ACE_Control_Block::dump (void) const
+{
+ ACE_TRACE ("ACE_Control_Block::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Name Node:\n")));
+ for (ACE_Name_Node *nextn = this->name_head_;
+ nextn != 0;
+ nextn = nextn->next_)
+ nextn->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("freep_ = %x"), (ACE_Malloc_Header *) this->freep_));
+ this->base_.dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nMalloc Header:\n")));
+ for (ACE_Malloc_Header *nexth = ((ACE_Malloc_Header *)this->freep_)->next_block_;
+ nexth != 0 && nexth != &this->base_;
+ nexth = nexth->next_block_)
+ nexth->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_Control_Block::ACE_Name_Node::ACE_Name_Node (void)
+{
+ ACE_TRACE ("ACE_Control_Block::ACE_Name_Node::ACE_Name_Node");
+}
+
+ACE_Control_Block::ACE_Name_Node::ACE_Name_Node (const char *name,
+ char *name_ptr,
+ char *pointer,
+ ACE_Name_Node *next)
+ : name_ (name_ptr),
+ pointer_ (pointer),
+ next_ (next),
+ prev_ (0)
+{
+ ACE_TRACE ("ACE_Control_Block::ACE_Name_Node::ACE_Name_Node");
+ char *n = this->name_;
+ ACE_OS::strcpy (n, name);
+ if (next != 0)
+ next->prev_ = this;
+}
+
+ACE_Control_Block::ACE_Name_Node::ACE_Name_Node (const ACE_Name_Node &)
+{
+ ACE_TRACE ("ACE_Control_Block::ACE_Name_Node::ACE_Name_Node");
+#if !defined (ACE_PSOS)
+ ACE_ASSERT (!"not implemented!");
+#endif /* ! ACE_PSOS */
+}
+
+const char *
+ACE_Control_Block::ACE_Name_Node::name (void) const
+{
+ const char *c = this->name_;
+ return c;
+}
+
+void
+ACE_Control_Block::ACE_Name_Node::name (const char *)
+{
+#if !defined (ACE_PSOS)
+ ACE_ASSERT (0 == "not implemented!");
+#endif /* ! ACE_PSOS */
+}
+
+ACE_Control_Block::ACE_Malloc_Header::ACE_Malloc_Header (void)
+ : next_block_ (0),
+ size_ (0)
+{
+}
+
+void
+ACE_Control_Block::ACE_Name_Node::dump (void) const
+{
+ ACE_TRACE ("ACE_Control_Block::ACE_Name_Node::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("pointer = %x"), (const char *) this->pointer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnext_ = %x"), (ACE_Name_Node *) this->next_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("\nname_ = (%x, %s)"),
+ (const char *) this->name_,
+ (const char *) this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#endif /* ACE_MALLOC_CPP */
diff --git a/ace/Memory/Malloc.h b/ace/Memory/Malloc.h
new file mode 100644
index 00000000000..152bf827936
--- /dev/null
+++ b/ace/Memory/Malloc.h
@@ -0,0 +1,414 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Malloc.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt and Irfan Pyarali
+ */
+//=============================================================================
+
+#ifndef ACE_MALLOC_H
+#define ACE_MALLOC_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_HAS_MALLOC_STATS)
+#if defined (ACE_HAS_THREADS)
+#include "ace/Process_Mutex.h"
+#define ACE_PROCESS_MUTEX ACE_Process_Mutex
+#else
+#include "ace/SV_Semaphore_Simple.h"
+#define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple
+#endif /* ACE_HAS_THREADS */
+
+typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT;
+
+/******************************************************************
+
+* Assume that ACE_MALLOC_ALIGN is the number of bytes of the alignment
+ of the platform. Usually, this will be 4 on most platforms. Some
+ platforms require this to be 8. In any case, this macro should
+ always be a 2's power.
+
+* Malloc_Header structure.
+
+ Notice that sizeof (ACE_Malloc_Header) must be multiple of
+ ACE_MALLOC_ALIGN
+
+ +-----------------------------------------+
+ |MALLOC_HEADER_PTR *next_block_; |
+ | // Points to next free Malloc_Header |
+ | // in this chain. |
+ +-----------------------------------------+
+ |size_t size_; |
+ | // Size of buffer associate with |
+ | // this Malloc_Header |
+ } // The size is in number of |
+ | // Malloc_Header (including this one.)|
+ +-----------------------------------------+
+ |long paddings_[ACE_MALLOC_PADDING_SIZE]; |
+ | // Padding long array. This purpose |
+ | // of this padding array is to adjust |
+ | // the sizeof (Malloc_Header) to be |
+ | // multiple of ACE_MALLOC_ALIGN. |
+ | // If you are sure that |
+ | // sizeof (MALLOC_HEADER_PTR) |
+ | // + sizeof (size_t) is a multiple |
+ | // of ACE_MALLOC_ALIGN, then you can |
+ | // #define ACE_MALLOC_PADDING_SIZE 0 |
+ | // to complete remove this data member|
+ | // from Malloc_Header. Otherwise, |
+ | // ACE will try to figure out the |
+ | // correct value of this macro. |
+ | // However, the calculation does not |
+ | // always do the right thing and in |
+ | // some rare cases, you'll need to |
+ | // tweak this value by defining the |
+ | // macro (ACE_MALLOC_PADDING_SIZE) |
+ | // explicitly. |
+ +-----------------------------------------+
+
+* Name_Node
+
+ ACE_Malloc allows searching thru it's allocated buffer using names.
+ Name_Node is an internal data structure that ACE_Malloc used to
+ maintain a linked list that manages this (name, buffer) mappings.
+
+ +-----------------------------------------+
+ |char *name_; |
+ | // Points to a dynamically allocated |
+ | // char buffer that holds the name |
+ | // of this node. This buffer is |
+ | // allocated from using this |
+ | // ACE_MALLOC instance that owns this |
+ | // Name_Node (so it always points to |
+ | // a buffer owned by its Malloc. |
+ +-----------------------------------------+
+ |char *pointer_; |
+ | // Points to the content that <name_> |
+ | // referring to. Like <name_>, the |
+ | // context always resides within the |
+ | // Malloc. |
+ +-----------------------------------------+
+ |NAME_NODE_PTR next_; |
+ +-----------------------------------------+
+ |NAME_NODE_PTR prev_; |
+ | // Name Node linked list pointers. |
+ +-----------------------------------------+
+
+
+* Control_Block
+
+ Only the first ACE_Malloc instance that uses
+ the shared memory will initialize the control block because all
+ later instances are supposed to share the memory with the first
+ instance. The following diagram shows the initial value of a
+ Control_Block.
+
+ +-----------------------------------------+
+ |NAME_NODE_PTR name_head_; |<---- NULL
+ | // Entry point for double-linked list.|
+ | // Initialized to NULL pointer to |
+ | // indicate an empty list. |
+ +-----------------------------------------+
+ |MALLOC_HEADER_PTR freep_; |
+ | // Pointer to last un-allocated |
+ | // malloc_header linked list. |---+
+ +-----------------------------------------+ |
+ |char lock_name_[MAXNAMELEN]; | |
+ | // The global name of the lock. | |
+ +-----------------------------------------+ |
+ |Malloc_Stats malloc_stats_; | |
+ | // (Optional statistic information. | |
+ | // Do not exist if | |
+ | // ACE_HAS_MALLOC_STATS is not | |
+ | // defined. | |
+ +-----------------------------------------+ |
+ |long align_[CONTROL_BLOCK_ALIGN_LONGS]; | |
+ | // | |
+ +-----------------------------------------+ |
+ |Malloc_Header base_; |<--+
+ | // Dummy node used to anchor the |
+ | // freelist. |<--+
+ | +-------------+ |
+ | |next_ |---+
+ | +-------------+
+ | |size_ |----> 0
+ +-----------------------------------------+
+
+ The first ACE_Malloc initializes the control block by allocating a
+ memory block of size equal to or greater than sizeof (control block)
+ (rounded to the closest <rounded_bytes>) and invokes the placement
+ new's on to initialize the control block and its internal
+ pointers/data structures. If the extra memory (memory after the
+ <base_> in the following diagram) is enough to create a
+ Malloc_Header chain, one is created and added to the freelist list.
+ That is, if the memory size returned by init_acquire() is greater
+ than the sizeof Control_Block, the control block is initialized to
+ the following diagram:
+
+
+ +-------------------------------------
+ |name_head_; |
+ +-------------------------------------+
+ |MALLOC_HEADER_PTR freep_; |--+
+ +-------------------------------------+ |
+ |lock_name_[...]; | |
+ +-------------------------------------+ |
+ |malloc_stats_; (Optional) | |
+ +-------------------------------------+ |
+ |align_[...]; | |
+ +-------------------------------------+ |
+ |Malloc_Header base_; |<-+
+ | +-----------+
+ | |next_; |--+
+ | +-----------+ |
+ | |size_ = 0; | |
+ +=====================================+ |
+ |Malloc_Header base_; |<-+
+ | +-----------+
+ | |next_; |
+ | +-----------+
+ | |size_ = 3; |
+ +-------------------------------------+
+ |Malloc_Header base_; |
+ | +-----------+
+ | (Uninitialized) |next_; |
+ | +-----------+
+ | |size_; |
+ +-------------------------------------+
+ |Malloc_Header base_; |
+ | +-----------+
+ | (Uninitialized) |next_; |
+ | +-----------+
+ | |size_; |
+ +-------------------------------------+
+
+***********************************************************/
+
+/// This keeps stats on the usage of the memory manager.
+struct ACE_Export ACE_Malloc_Stats
+{
+ ACE_Malloc_Stats (void);
+ void dump (void) const;
+
+ /// Coarse-grained unit of allocation.
+ ACE_INT nchunks_;
+
+ /// Fine-grained unit of allocation.
+ ACE_INT nblocks_;
+
+ /// Number of blocks in use
+ ACE_INT ninuse_;
+};
+#define ACE_MALLOC_STATS(X) X
+#else
+#define ACE_MALLOC_STATS(X)
+#endif /* ACE_HAS_MALLOC_STATS */
+
+#if !defined (ACE_MALLOC_PADDING)
+// ACE_MALLOC_PADDING allows you to insure that allocated regions are
+// at least <ACE_MALLOC_PADDING> bytes long. It is especially useful
+// when you want areas to be at least a page long, or 32K long, or
+// something like that. It doesn't guarantee alignment to an address
+// multiple, like 8-byte data alignment, etc. The allocated area's
+// padding to your selected size is done with an added array of long[]
+// and your compiler will decide how to align things in memory.
+
+#define ACE_MALLOC_PADDING 1
+#endif /* ACE_MALLOC_PADDING */
+
+#if !defined (ACE_MALLOC_ALIGN)
+// Align the malloc header size to a multiple of a double.
+#define ACE_MALLOC_ALIGN (sizeof (double))
+#endif /* ACE_MALLOC_ALIGN */
+
+// ACE_MALLOC_HEADER_SIZE is the normalized malloc header size.
+#define ACE_MALLOC_HEADER_SIZE (ACE_MALLOC_PADDING % ACE_MALLOC_ALIGN == 0 \
+ ? ACE_MALLOC_PADDING \
+ : (((ACE_MALLOC_PADDING / ACE_MALLOC_ALIGN) + 1) \
+ * ACE_MALLOC_ALIGN))
+
+/**
+ * @class ACE_Control_Block
+ *
+ * @brief This information is stored in memory allocated by the <Memory_Pool>.
+ *
+ * This class defines the "old" control block class for use in
+ * ACE_Malloc_T. This control block implementation is
+ * considerable more efficient than the "position independent"
+ * one below (ACE_PI_Control_Block) but if you are going to use
+ * it to construct a ACE_Malloc_T and access the memory from
+ * several different processes, you must "map" the underlying
+ * memory pool to the same address.
+ */
+class ACE_Export ACE_Control_Block
+{
+public:
+
+ /**
+ * @class ACE_Malloc_Header
+ *
+ * @brief This is the control block header. It's used by <ACE_Malloc>
+ * to keep track of each chunk of data when it's in the free
+ * list or in use.
+ */
+ class ACE_Export ACE_Malloc_Header
+ {
+ public:
+ ACE_Malloc_Header (void);
+
+ /// Points to next block if on free list.
+ ACE_Malloc_Header *next_block_;
+
+ /// Initialize a malloc header pointer.
+ static void init_ptr (ACE_Malloc_Header **ptr,
+ ACE_Malloc_Header *init,
+ void *base_addr);
+
+ /// Size of this header control block.
+ size_t size_;
+
+#if defined (ACE_MALLOC_PADDING_SIZE) && (ACE_MALLOC_PADDING_SIZE == 0)
+ // No padding required.
+#else
+# if !defined (ACE_MALLOC_PADDING_SIZE)
+# define ACE_MALLOC_PADDING_SIZE ((int) (ACE_MALLOC_HEADER_SIZE - \
+ (sizeof (ACE_Malloc_Header*) + sizeof (size_t)))\
+ / (int) sizeof (long))
+# endif /* !ACE_MALLOC_PADDING_SIZE */
+ long padding_[ACE_MALLOC_PADDING_SIZE < 1 ? 1 : ACE_MALLOC_PADDING_SIZE];
+#endif /* ACE_MALLOC_PADDING_SIZE && ACE_MALLOC_PADDING_SIZE == 0 */
+
+ /// Dump the state of the object.
+ void dump (void) const;
+ };
+
+ /**
+ * @class ACE_Name_Node
+ *
+ * @brief This class supports "named memory regions" within <ACE_Malloc>.
+ *
+ * Internally, the named memory regions are stored as a
+ * doubly-linked list within the <Memory_Pool>. This makes
+ * it easy to iterate over the items in the list in both FIFO
+ * and LIFO order.
+ */
+ class ACE_Export ACE_Name_Node
+ {
+ public:
+ // = Initialization methods.
+ /// Constructor.
+ ACE_Name_Node (const char *name,
+ char *name_ptr,
+ char *pointer,
+ ACE_Name_Node *head);
+
+ /// Copy constructor.
+ ACE_Name_Node (const ACE_Name_Node &);
+
+ /// Constructor.
+ ACE_Name_Node (void);
+
+ /// Constructor.
+ ~ACE_Name_Node (void);
+
+ /// Initialize a name node pointer.
+ static void init_ptr (ACE_Name_Node **ptr,
+ ACE_Name_Node *init,
+ void *base_addr);
+
+ /// Return a pointer to the name of this node.
+ const char *name (void) const;
+
+ /// Assign a name;
+ void name (const char *);
+
+ /// Name of the Node.
+ char *name_;
+
+ /// Pointer to the contents.
+ char *pointer_;
+
+ /// Pointer to the next node in the doubly-linked list.
+ ACE_Name_Node *next_;
+
+ /// Pointer to the previous node in the doubly-linked list.
+ ACE_Name_Node *prev_;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+ };
+
+ /// Print out a bunch of size info for debugging.
+ static void print_alignment_info (void);
+
+ /// Reference counter.
+ int ref_counter_;
+
+ /// Head of the linked list of Name Nodes.
+ ACE_Name_Node *name_head_;
+
+ /// Current head of the freelist.
+ ACE_Malloc_Header *freep_;
+
+ /// Name of lock thats ensures mutual exclusion.
+ char lock_name_[MAXNAMELEN];
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ /// Keep statistics about ACE_Malloc state and performance.
+ ACE_Malloc_Stats malloc_stats_;
+#define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \
+ + sizeof (ACE_Malloc_Header*) \
+ + sizeof (int) \
+ + MAXNAMELEN \
+ + sizeof (ACE_Malloc_Stats)))
+#else
+#define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \
+ + sizeof (ACE_Malloc_Header*) \
+ + sizeof (int) \
+ + MAXNAMELEN))
+#endif /* ACE_HAS_MALLOC_STATS */
+
+// Notice the casting to int for <sizeof> otherwise unsigned int
+// arithmetic is used and some awful things may happen.
+#if defined (ACE_CONTROL_BLOCK_ALIGN_LONGS) && (ACE_CONTROL_BLOCK_ALIGN_LONGS == 0)
+ // No padding required in control block.
+#else
+# if !defined (ACE_CONTROL_BLOCK_ALIGN_LONGS)
+# define ACE_CONTROL_BLOCK_ALIGN_LONGS \
+ ((ACE_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN != 0 \
+ ? ACE_MALLOC_ALIGN - (ACE_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN) \
+ : ACE_MALLOC_ALIGN) / int (sizeof (long)))
+# endif /* !ACE_CONTROL_BLOCK_ALIGN_LONGS */
+ long align_[ACE_CONTROL_BLOCK_ALIGN_LONGS < 1 ? 1 : ACE_CONTROL_BLOCK_ALIGN_LONGS];
+ // Force alignment.
+#endif /* ACE_CONTROL_BLOCK_ALIGN_LONGS && ACE_CONTROL_BLOCK_ALIGN_LONGS == 0 */
+
+ /// Dummy node used to anchor the freelist. This needs to come last...
+ ACE_Malloc_Header base_;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc.i"
+#endif /* __ACE_INLINE__ */
+
+// Include the ACE_Malloc templates and ACE_Memory_Pool classes at this point.
+#include "ace/Malloc_T.h"
+#include "ace/Memory_Pool.h"
+
+#include "ace/post.h"
+#endif /* ACE_MALLOC_H */
diff --git a/ace/Memory/Malloc.i b/ace/Memory/Malloc.i
new file mode 100644
index 00000000000..76722f13fb7
--- /dev/null
+++ b/ace/Memory/Malloc.i
@@ -0,0 +1,21 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+ACE_Control_Block::ACE_Name_Node::~ACE_Name_Node (void)
+{
+}
+
+ACE_INLINE void
+ACE_Control_Block::ACE_Malloc_Header::init_ptr
+ (ACE_Malloc_Header **ptr, ACE_Malloc_Header *init, void *)
+{
+ *ptr = init;
+}
+
+ACE_INLINE void
+ACE_Control_Block::ACE_Name_Node::init_ptr
+ (ACE_Name_Node **ptr, ACE_Name_Node *init, void *)
+{
+ *ptr = init;
+}
diff --git a/ace/Memory/Malloc_Allocator.cpp b/ace/Memory/Malloc_Allocator.cpp
new file mode 100644
index 00000000000..5f98c01746a
--- /dev/null
+++ b/ace/Memory/Malloc_Allocator.cpp
@@ -0,0 +1,165 @@
+// $Id$
+
+// FILENAME
+// Malloc_Allocator.cpp
+//
+// AUTHOR
+// Priyanka Gontla <pgontla@uci.edu>
+//
+// ==========================================================================
+
+#if !defined (ACE_MALLOC_ALLOCATOR_CPP)
+#define ACE_MALLOC_ALLOCATOR_CPP
+
+#include "ace/Malloc_Allocator.h"
+#include "ace/Object_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc_Allocator.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Synch_T.h"
+
+ACE_RCSID (ace, Malloc_Allocator, "$Id$")
+
+ACE_Allocator *
+ACE_Allocator::instance (void)
+{
+ // ACE_TRACE ("ACE_Allocator::instance");
+
+ if (ACE_Allocator::allocator_ == 0)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ACE_Allocator::allocator_ == 0)
+ {
+ // Have a seat. We want to avoid ever having to delete the
+ // ACE_Allocator instance, to avoid shutdown order
+ // dependencies. ACE_New_Allocator never needs to be
+ // destroyed: its destructor is empty and its instance
+ // doesn't have any state. Therefore, sizeof
+ // ACE_New_Allocator is equal to sizeof void *. It's
+ // instance just contains a pointer to its virtual function
+ // table.
+ //
+ // So, we allocate space for the ACE_New_Allocator instance
+ // in the data segment. Because its size is the same as
+ // that of a pointer, we allocate it as a pointer so that it
+ // doesn't get constructed statically. We never bother to
+ // destroy it.
+ static void *allocator_instance = 0;
+
+ // Check this critical assumption. We put it in a variable
+ // first to avoid stupid compiler warnings that the
+ // condition may always be true/false.
+# if !defined (ACE_NDEBUG)
+ int assertion = (sizeof allocator_instance ==
+ sizeof (ACE_New_Allocator));
+ ACE_ASSERT (assertion);
+# endif /* !ACE_NDEBUG */
+
+ // Initialize the allocator_instance by using a placement
+ // new.
+ ACE_Allocator::allocator_ =
+ new (&allocator_instance) ACE_New_Allocator;
+ }
+ }
+
+ return ACE_Allocator::allocator_;
+}
+
+ACE_Allocator *
+ACE_Allocator::instance (ACE_Allocator *r)
+{
+ ACE_TRACE ("ACE_Allocator::instance");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+ ACE_Allocator *t = ACE_Allocator::allocator_;
+
+ // We can't safely delete it since we don't know who created it!
+ ACE_Allocator::delete_allocator_ = 0;
+
+ ACE_Allocator::allocator_ = r;
+ return t;
+}
+
+void
+ACE_Allocator::close_singleton (void)
+{
+ ACE_TRACE ("ACE_Allocator::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ if (ACE_Allocator::delete_allocator_)
+ {
+ // This should never be executed.... See the
+ // ACE_Allocator::instance (void) method for an explanation.
+ delete ACE_Allocator::allocator_;
+ ACE_Allocator::allocator_ = 0;
+ ACE_Allocator::delete_allocator_ = 0;
+ }
+}
+
+ACE_Allocator::~ACE_Allocator (void)
+{
+ ACE_TRACE ("ACE_Allocator::~ACE_Allocator");
+}
+
+ACE_Allocator::ACE_Allocator (void)
+{
+ ACE_TRACE ("ACE_Allocator::ACE_Allocator");
+}
+
+void
+ACE_Static_Allocator_Base::dump (void) const
+{
+ ACE_TRACE ("ACE_Static_Allocator_Base::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\noffset_ = %d"), this->offset_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize_ = %d\n"), this->size_));
+ ACE_HEX_DUMP ((LM_DEBUG, this->buffer_, this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ACE_Malloc_Stats::ACE_Malloc_Stats (void)
+ : nblocks_ (0),
+ nchunks_ (0),
+ ninuse_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_Stats::ACE_Malloc_Stats");
+}
+
+void
+ACE_Malloc_Stats::dump (void) const
+{
+ ACE_TRACE ("ACE_Malloc_Stats::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ int nblocks = this->nblocks_.value ();
+ int ninuse = this->ninuse_.value ();
+ int nchunks = this->nchunks_.value ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("nblocks = %d"), nblocks));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\nninuse = %d"), ninuse));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\nnchunks = %d"), nchunks));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Atomic_Op<ACE_PROCESS_MUTEX, int>;
+template class ACE_Atomic_Op_Ex<ACE_PROCESS_MUTEX, int>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Atomic_Op<ACE_PROCESS_MUTEX, int>
+#pragma instantiate ACE_Atomic_Op_Ex<ACE_PROCESS_MUTEX, int>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+#endif /* ACE_HAS_MALLOC_STATS */
+
+#endif /* ACE_MALLOC_ALLOCATOR_CPP */
diff --git a/ace/Memory/Malloc_Allocator.h b/ace/Memory/Malloc_Allocator.h
new file mode 100644
index 00000000000..b932adb74f4
--- /dev/null
+++ b/ace/Memory/Malloc_Allocator.h
@@ -0,0 +1,161 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Malloc_Allocator.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ */
+//=============================================================================
+
+#ifndef MALLOC_ALLOCATOR_H
+#define MALLOC_ALLOCATOR_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc_Base.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_HAS_MALLOC_STATS)
+#include "ace/Synch_T.h"
+#if defined (ACE_HAS_THREADS)
+#define ACE_PROCESS_MUTEX ACE_Process_Mutex
+#else
+#include "ace/SV_Semaphore_Simple.h"
+#define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple
+#endif /* ACE_HAS_THREADS */
+
+typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT;
+
+/// This keeps stats on the usage of the memory manager.
+struct ACE_Export ACE_Malloc_Stats
+{
+ ACE_Malloc_Stats (void);
+ void dump (void) const;
+
+ /// Coarse-grained unit of allocation.
+ ACE_INT nchunks_;
+
+ /// Fine-grained unit of allocation.
+ ACE_INT nblocks_;
+
+ /// Number of blocks in use
+ ACE_INT ninuse_;
+};
+#define ACE_MALLOC_STATS(X) X
+#else
+#define ACE_MALLOC_STATS(X)
+#endif /* ACE_HAS_MALLOC_STATS */
+
+/**
+ * @class ACE_New_Allocator
+ *
+ * @brief Defines a class that provided a simple implementation of
+ * memory allocation.
+ *
+ * This class uses the new/delete operators to allocate and free up
+ * memory. Please note that the only methods that are supported are
+ * <malloc>, <calloc>, and <free>. All other methods are no-ops that
+ * return -1 and set <errno> to <ENOTSUP>. If you require this
+ * functionality, please use: ACE_Allocator_Adapter <ACE_Malloc
+ * <ACE_LOCAL_MEMORY_POOL, MUTEX> >, which will allow you to use the
+ * added functionality of bind/find/etc. while using the new/delete
+ * operators.
+ */
+class ACE_Export ACE_New_Allocator : public ACE_Allocator
+{
+public:
+ /// These methods are defined.
+ virtual void *malloc (size_t nbytes);
+ virtual void *calloc (size_t nbytes, char initial_value = '\0');
+ virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0');
+ virtual void free (void *ptr);
+
+ /// These methods are no-ops.
+ virtual int remove (void);
+ virtual int bind (const char *name, void *pointer, int duplicates = 0);
+ virtual int trybind (const char *name, void *&pointer);
+ virtual int find (const char *name, void *&pointer);
+ virtual int find (const char *name);
+ virtual int unbind (const char *name);
+ virtual int unbind (const char *name, void *&pointer);
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+#if defined (ACE_HAS_MALLOC_STATS)
+ virtual void print_stats (void) const;
+#endif /* ACE_HAS_MALLOC_STATS */
+ virtual void dump (void) const;
+
+private:
+ // DO NOT ADD ANY STATE (DATA MEMBERS) TO THIS CLASS!!!! See the
+ // <ACE_Allocator::instance> implementation for explanation.
+};
+
+/**
+ * @class ACE_Static_Allocator_Base
+ *
+ * @brief Defines a class that provided a highly optimized memory
+ * management scheme for allocating memory statically.
+ *
+ * This class manages a fixed-size <POOL_SIZE> of memory. Every
+ * time <malloc>/<calloc> is called, it simply moves an internal
+ * index forward and returns a pointer to the requested chunk.
+ * All memory is allocated statically (typically via the
+ * <ACE_Static_Allocator> template) and <free> is a no-op. This
+ * behavior is useful for use-cases where all the memory
+ * allocation needs are known in advance and no deletions ever
+ * occur.
+ */
+class ACE_Export ACE_Static_Allocator_Base : public ACE_Allocator
+{
+public:
+ ACE_Static_Allocator_Base (char *buffer, size_t size);
+ virtual void *malloc (size_t nbytes);
+ virtual void *calloc (size_t nbytes, char initial_value = '\0');
+ virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0');
+ virtual void free (void *ptr);
+ virtual int remove (void);
+ virtual int bind (const char *name, void *pointer, int duplicates = 0);
+ virtual int trybind (const char *name, void *&pointer);
+ virtual int find (const char *name, void *&pointer);
+ virtual int find (const char *name);
+ virtual int unbind (const char *name);
+ virtual int unbind (const char *name, void *&pointer);
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+#if defined (ACE_HAS_MALLOC_STATS)
+ virtual void print_stats (void) const;
+#endif /* ACE_HAS_MALLOC_STATS */
+ virtual void dump (void) const;
+
+protected:
+ /// Don't allow direct instantiations of this class.
+ ACE_Static_Allocator_Base (void);
+
+ /// Pointer to the buffer.
+ char *buffer_;
+
+ /// Size of the buffer.
+ size_t size_;
+
+ /// Pointer to the current offset in the <buffer_>.
+ size_t offset_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc_Allocator.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* MALLOC_ALLOCATOR_H */
diff --git a/ace/Memory/Malloc_Allocator.i b/ace/Memory/Malloc_Allocator.i
new file mode 100644
index 00000000000..b0cfd89b218
--- /dev/null
+++ b/ace/Memory/Malloc_Allocator.i
@@ -0,0 +1,239 @@
+// $Id$
+
+ACE_INLINE void *
+ACE_New_Allocator::malloc (size_t nbytes)
+{
+ char *ptr = 0;
+
+ if (nbytes > 0)
+ ACE_NEW_RETURN (ptr, char[nbytes], 0);
+ return (void *) ptr;
+}
+
+ACE_INLINE void *
+ACE_New_Allocator::calloc (size_t nbytes,
+ char initial_value)
+{
+ char *ptr = 0;
+
+ ACE_NEW_RETURN (ptr, char[nbytes], 0);
+
+ ACE_OS::memset (ptr, initial_value, nbytes);
+ return (void *) ptr;
+}
+
+ACE_INLINE void *
+ACE_New_Allocator::calloc (size_t n_elem, size_t elem_size, char initial_value)
+{
+ return ACE_New_Allocator::calloc (n_elem * elem_size, initial_value);
+}
+
+ACE_INLINE void
+ACE_New_Allocator::free (void *ptr)
+{
+ delete [] (char *) ptr;
+}
+
+ACE_INLINE int
+ACE_New_Allocator::remove (void)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::bind (const char *, void *, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::trybind (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::find (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::find (const char *)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::unbind (const char *)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::unbind (const char *, void *&)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::sync (ssize_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::sync (void *, size_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::protect (ssize_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+ACE_INLINE int
+ACE_New_Allocator::protect (void *, size_t, int)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ACE_INLINE void
+ACE_New_Allocator::print_stats (void) const
+{
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ACE_INLINE void
+ACE_New_Allocator::dump (void) const
+{
+}
+
+ACE_INLINE void *
+ACE_Static_Allocator_Base::malloc (size_t nbytes)
+{
+ if (this->offset_ + nbytes > this->size_)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ else
+ {
+ // Record the current offset, increment the offset by the number
+ // of bytes requested, and return the original offset.
+ char *ptr = &this->buffer_[this->offset_];
+ this->offset_ += nbytes;
+ return (void *) ptr;
+ }
+}
+
+ACE_INLINE void *
+ACE_Static_Allocator_Base::calloc (size_t nbytes,
+ char initial_value)
+{
+ void *ptr = this->malloc (nbytes);
+
+ ACE_OS::memset (ptr, initial_value, nbytes);
+ return (void *) ptr;
+}
+
+ACE_INLINE void *
+ACE_Static_Allocator_Base::calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value)
+{
+ return this->calloc (n_elem * elem_size, initial_value);
+}
+
+ACE_INLINE void
+ACE_Static_Allocator_Base::free (void *ptr)
+{
+ // Check to see if ptr is within our pool?!
+ ACE_UNUSED_ARG (ptr);
+ ACE_ASSERT (ptr >= this->buffer_ && ptr < this->buffer_ + this->size_);
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::remove (void)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::bind (const char *, void *, int)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::trybind (const char *, void *&)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::find (const char *, void *&)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::find (const char *)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::unbind (const char *)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::unbind (const char *, void *&)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::sync (ssize_t, int)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::sync (void *, size_t, int)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::protect (ssize_t, int)
+{
+ return -1;
+}
+
+ACE_INLINE int
+ACE_Static_Allocator_Base::protect (void *, size_t, int)
+{
+ return -1;
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ACE_INLINE void
+ACE_Static_Allocator_Base::print_stats (void) const
+{
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ACE_INLINE
+ACE_Static_Allocator_Base::ACE_Static_Allocator_Base (char *buffer,
+ size_t size)
+ : buffer_ (buffer),
+ size_ (size),
+ offset_ (0)
+{
+}
diff --git a/ace/Memory/Malloc_Base.h b/ace/Memory/Malloc_Base.h
new file mode 100644
index 00000000000..3b9f5c7161f
--- /dev/null
+++ b/ace/Memory/Malloc_Base.h
@@ -0,0 +1,156 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Malloc_Base.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt and Irfan Pyarali
+ */
+//=============================================================================
+
+
+#ifndef ACE_MALLOC_BASE_H
+#define ACE_MALLOC_BASE_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// The definition of this class is located in Malloc.cpp.
+
+/**
+ * @class ACE_Allocator
+ *
+ * @brief Interface for a dynamic memory allocator that uses inheritance
+ * and dynamic binding to provide extensible mechanisms for
+ * allocating and deallocating memory.
+ */
+class ACE_Export ACE_Allocator
+{
+public:
+ // = Memory Management
+
+ /// Get pointer to a default <ACE_Allocator>.
+ static ACE_Allocator *instance (void);
+
+ /// Set pointer to a process-wide <ACE_Allocator> and return existing
+ /// pointer.
+ static ACE_Allocator *instance (ACE_Allocator *);
+
+ /// Delete the dynamically allocated Singleton
+ static void close_singleton (void);
+
+ /// "No-op" constructor (needed to make certain compilers happy).
+ ACE_Allocator (void);
+
+ /// Virtual destructor
+ virtual ~ACE_Allocator (void);
+
+ /// Allocate <nbytes>, but don't give them any initial value.
+ virtual void *malloc (size_t nbytes) = 0;
+
+ /// Allocate <nbytes>, giving them <initial_value>.
+ virtual void *calloc (size_t nbytes, char initial_value = '\0') = 0;
+
+ /// Allocate <n_elem> each of size <elem_size>, giving them
+ /// <initial_value>.
+ virtual void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0') = 0;
+
+ /// Free <ptr> (must have been allocated by <ACE_Allocator::malloc>).
+ virtual void free (void *ptr) = 0;
+
+ /// Remove any resources associated with this memory manager.
+ virtual int remove (void) = 0;
+
+ // = Map manager like functions
+
+ /**
+ * Associate <name> with <pointer>. If <duplicates> == 0 then do
+ * not allow duplicate <name>/<pointer> associations, else if
+ * <duplicates> != 0 then allow duplicate <name>/<pointer>
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound <name> or (2) <duplicates> != 0, returns 1 if trying to
+ * bind a previously bound <name> and <duplicates> == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ virtual int bind (const char *name, void *pointer, int duplicates = 0) = 0;
+
+ /**
+ * Associate <name> with <pointer>. Does not allow duplicate
+ * <name>/<pointer> associations. Returns 0 if successfully binds
+ * (1) a previously unbound <name>, 1 if trying to bind a previously
+ * bound <name>, or returns -1 if a resource failure occurs. When
+ * this call returns <pointer>'s value will always reference the
+ * void * that <name> is associated with. Thus, if the caller needs
+ * to use <pointer> (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ virtual int trybind (const char *name, void *&pointer) = 0;
+
+ /// Locate <name> and pass out parameter via pointer. If found,
+ /// return 0, Returns -1 if failure occurs.
+ virtual int find (const char *name, void *&pointer) = 0;
+
+ /// returns 0 if the name is in the mapping. -1, otherwise.
+ virtual int find (const char *name) = 0;
+
+ /// Unbind (remove) the name from the map. Don't return the pointer
+ /// to the caller
+ virtual int unbind (const char *name) = 0;
+
+ /// Break any association of name. Returns the value of pointer in
+ /// case the caller needs to deallocate memory.
+ virtual int unbind (const char *name, void *&pointer) = 0;
+
+ // = Protection and "sync" (i.e., flushing memory to persistent
+ // backing store).
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If <len> == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC) = 0;
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC) = 0;
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR) = 0;
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR) = 0;
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ /// Dump statistics of how malloc is behaving.
+ virtual void print_stats (void) const = 0;
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ /// Dump the state of the object.
+ virtual void dump (void) const = 0;
+private:
+ // DO NOT ADD ANY STATE (DATA MEMBERS) TO THIS CLASS!!!! See the
+ // <ACE_Allocator::instance> implementation for explanation.
+
+ /// Pointer to a process-wide <ACE_Allocator> instance.
+ static ACE_Allocator *allocator_;
+
+ /// Must delete the <allocator_> if non-0.
+ static int delete_allocator_;
+};
+
+#include "ace/post.h"
+#endif /* ACE_MALLOC_BASE_H */
diff --git a/ace/Memory/Malloc_Instantiations.cpp b/ace/Memory/Malloc_Instantiations.cpp
new file mode 100644
index 00000000000..72ba9edea67
--- /dev/null
+++ b/ace/Memory/Malloc_Instantiations.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#include "ace/Malloc.h"
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX>;
+template class ACE_Malloc_T<ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX, ACE_Control_Block>;
+template class ACE_Allocator_Adapter<ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX> >;
+
+// Explicitly instantiate these templates in the multithreaded case
+// since some classes need them.
+# if defined (ACE_HAS_THREADS)
+template class ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex>;
+template class ACE_Malloc_T<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex, ACE_Control_Block>;
+template class ACE_Allocator_Adapter<ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex> >;
+# endif /* ACE_HAS_THREADS */
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX>
+#pragma instantiate ACE_Malloc_T<ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX, ACE_Control_Block>
+#pragma instantiate ACE_Allocator_Adapter<ACE_Malloc<ACE_LOCAL_MEMORY_POOL,ACE_SYNCH_MUTEX> >
+
+// Explicitly instantiate these templates in the multithreaded case
+// since some classes need them.
+# if defined (ACE_HAS_THREADS)
+# pragma instantiate ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex>
+# pragma instantiate ACE_Malloc_T<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex, ACE_Control_Block>
+# pragma instantiate ACE_Allocator_Adapter<ACE_Malloc<ACE_LOCAL_MEMORY_POOL, ACE_Null_Mutex> >
+# endif /* ACE_HAS_THREADS */
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Memory/Malloc_T.cpp b/ace/Memory/Malloc_T.cpp
new file mode 100644
index 00000000000..3eccefe3a5c
--- /dev/null
+++ b/ace/Memory/Malloc_T.cpp
@@ -0,0 +1,943 @@
+// Malloc_T.cpp
+// $Id$
+
+#ifndef ACE_MALLOC_T_C
+#define ACE_MALLOC_T_C
+
+#include "ace/Malloc_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc_T.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Malloc_T, "$Id$")
+
+template <class T, class ACE_LOCK>
+ACE_Cached_Allocator<T, ACE_LOCK>::ACE_Cached_Allocator (size_t n_chunks)
+ : pool_ (0),
+ free_list_ (ACE_PURE_FREE_LIST)
+{
+ ACE_NEW (this->pool_,
+ char[n_chunks * sizeof (T)]);
+
+ for (size_t c = 0;
+ c < n_chunks;
+ c++)
+ {
+ void* placement = this->pool_ + c * sizeof(T);
+ this->free_list_.add (new (placement) ACE_Cached_Mem_Pool_Node<T>);
+ }
+ // Put into free list using placement contructor, no real memory
+ // allocation in the above <new>.
+}
+
+template <class T, class ACE_LOCK>
+ACE_Cached_Allocator<T, ACE_LOCK>::~ACE_Cached_Allocator (void)
+{
+ delete [] this->pool_;
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Malloc_T)
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::protect (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::protect");
+ return this->allocator_.protect (len, flags);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::protect (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::protect");
+ return this->allocator_.protect (addr, len, flags);
+}
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const char *pool_name)
+ : allocator_ (ACE_TEXT_CHAR_TO_TCHAR (pool_name))
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+
+#if defined (ACE_HAS_WCHAR)
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const wchar_t *pool_name)
+ : allocator_ (ACE_TEXT_WCHAR_TO_TCHAR (pool_name))
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+#endif /* ACE_HAS_WCHAR */
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::~ACE_Allocator_Adapter (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::~ACE_Allocator_Adapter");
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::print_stats (void) const
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::print_stats");
+ this->allocator_.print_stats ();
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::dump (void) const
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::dump");
+ this->allocator_.dump ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->memory_pool_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("cb_ptr_ = %x"), this->cb_ptr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ this->cb_ptr_->dump ();
+#if defined (ACE_HAS_MALLOC_STATS)
+ if (this->cb_ptr_ != 0)
+ this->cb_ptr_->malloc_stats_.dump ();
+#endif /* ACE_HAS_MALLOC_STATS */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::print_stats (void) const
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::print_stats");
+ ACE_GUARD (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_);
+
+ if (this->cb_ptr_ == 0)
+ return;
+ this->cb_ptr_->malloc_stats_.dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) contents of freelist:\n")));
+
+ for (MALLOC_HEADER *currp = this->cb_ptr_->freep_->next_block_;
+ ;
+ currp = currp->next_block_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) ptr = %u, MALLOC_HEADER units = %d, byte units = %d\n"),
+ currp,
+ currp->size_,
+ currp->size_ * sizeof (MALLOC_HEADER)));
+ if (currp == this->cb_ptr_->freep_)
+ break;
+ }
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+// Put <ptr> in the free list (locked version).
+
+template<ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::free (void *ptr)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::free");
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+
+ this->shared_free (ptr);
+}
+
+// This function is called by the ACE_Malloc_T constructor to initialize
+// the memory pool. The first time in it allocates room for the
+// control block (as well as a chunk of memory, depending on
+// rounding...). Depending on the type of <MEM_POOL> (i.e., shared
+// vs. local) subsequent calls from other processes will only
+// initialize the control block pointer.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::open (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::open");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ size_t rounded_bytes = 0;
+ int first_time = 0;
+
+ this->cb_ptr_ = (ACE_CB *)
+ this->memory_pool_.init_acquire (sizeof *this->cb_ptr_,
+ rounded_bytes,
+ first_time);
+ if (this->cb_ptr_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("init_acquire failed")),
+ -1);
+ else if (first_time)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) first time in, control block = %u\n"), this->cb_ptr_));
+
+ MALLOC_HEADER::init_ptr (&this->cb_ptr_->freep_,
+ &this->cb_ptr_->base_,
+ this->cb_ptr_);
+
+ MALLOC_HEADER::init_ptr (&this->cb_ptr_->freep_->next_block_,
+ this->cb_ptr_->freep_,
+ this->cb_ptr_);
+
+ NAME_NODE::init_ptr (&this->cb_ptr_->name_head_,
+ 0,
+ this->cb_ptr_);
+
+ this->cb_ptr_->freep_->size_ = 0;
+ this->cb_ptr_->ref_counter_ = 1;
+
+ if (rounded_bytes > (sizeof *this->cb_ptr_ + sizeof (MALLOC_HEADER)))
+ {
+ // If we've got any extra space at the end of the control
+ // block, then skip past the dummy <MALLOC_HEADER> to
+ // point at the first free block.
+ MALLOC_HEADER *p = ((MALLOC_HEADER *) (this->cb_ptr_->freep_)) + 1;
+
+ MALLOC_HEADER::init_ptr (&p->next_block_,
+ 0,
+ this->cb_ptr_);
+
+ // Why aC++ in 64-bit mode can't grok this, I have no
+ // idea... but it ends up with an extra bit set which makes
+ // size_ really big without this hack.
+#if defined (__hpux) && defined (__LP64__)
+ size_t hpux11_hack = (rounded_bytes - sizeof *this->cb_ptr_)
+ / sizeof (MALLOC_HEADER);
+ p->size_ = hpux11_hack;
+#else
+ p->size_ = (rounded_bytes - sizeof *this->cb_ptr_)
+ / sizeof (MALLOC_HEADER);
+#endif /* (__hpux) && defined (__LP64__) */
+
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nchunks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+
+ // Insert the newly allocated chunk of memory into the free
+ // list. Add "1" to skip over the <MALLOC_HEADER> when
+ // freeing the pointer.
+ this->shared_free (p + 1);
+ }
+ }
+ else
+ ++this->cb_ptr_->ref_counter_;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name)
+ : memory_pool_ (pool_name),
+ lock_ (pool_name == 0 ? 0 : ACE::basename (pool_name,
+ ACE_DIRECTORY_SEPARATOR_CHAR))
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ if (this->open () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options)
+ : memory_pool_ (pool_name, options),
+ lock_ (lock_name != 0 ? lock_name : ACE::basename (pool_name,
+ ACE_DIRECTORY_SEPARATOR_CHAR))
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ if (this->open () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+
+#if !defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const void *options)
+ : memory_pool_ (pool_name,
+ (const ACE_MEM_POOL_OPTIONS *) options),
+ lock_ (lock_name)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ if (this->open () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_T (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEM_POOL>::~ACE_Malloc_T<MEM_POOL>");
+}
+
+// Clean up the resources allocated by ACE_Malloc_T.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::remove (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::remove");
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) destroying ACE_Malloc_T\n")));
+ int result = 0;
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ this->print_stats ();
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ // Remove the ACE_LOCK.
+ this->lock_.remove ();
+
+ // Give the memory pool a chance to release its resources.
+ result = this->memory_pool_.release ();
+
+ // Reset this->cb_ptr_ as it is no longer valid.
+ // There's also no need to keep the reference counter as the
+ // underlying memory pool has been destroyed.
+ // Also notice that we are leaving the decision of removing
+ // the pool to users so they can map to the same mmap file
+ // again.
+ this->cb_ptr_ = 0;
+
+ return result;
+}
+
+// General-purpose memory allocator. Assumes caller holds the locks.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_malloc (size_t nbytes)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_malloc");
+#endif /* !ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (this->cb_ptr_ == 0)
+ return 0;
+
+ // Round up request to a multiple of the MALLOC_HEADER size.
+ size_t nunits =
+ (nbytes + sizeof (MALLOC_HEADER) - 1) / sizeof (MALLOC_HEADER)
+ + 1; // Add one for the <MALLOC_HEADER> itself.
+
+ MALLOC_HEADER *prevp = 0;
+ MALLOC_HEADER *currp = 0;
+
+ ACE_SEH_TRY
+ {
+ // Begin the search starting at the place in the freelist where the
+ // last block was found.
+ prevp = this->cb_ptr_->freep_;
+ currp = prevp->next_block_;
+ }
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ currp = prevp->next_block_;
+ }
+#endif
+
+ // Search the freelist to locate a block of the appropriate size.
+
+
+ while (1)
+
+ // *Warning* Do not use "continue" within this while-loop.
+
+ {
+ ACE_SEH_TRY
+ {
+ if (currp->size_ >= nunits) // Big enough
+ {
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+ if (currp->size_ == nunits)
+ // Exact size, just update the pointers.
+ prevp->next_block_ = currp->next_block_;
+ else
+ {
+ // Remaining chunk is larger than requested block, so
+ // allocate at tail end.
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ currp->size_ -= nunits;
+ currp += currp->size_;
+ MALLOC_HEADER::init_ptr (&currp->next_block_,
+ 0,
+ this->cb_ptr_);
+ currp->size_ = nunits;
+ }
+ this->cb_ptr_->freep_ = prevp;
+
+ // Skip over the MALLOC_HEADER when returning pointer.
+ return currp + 1;
+ }
+ else if (currp == this->cb_ptr_->freep_)
+ {
+ // We've wrapped around freelist without finding a
+ // block. Therefore, we need to ask the memory pool for
+ // a new chunk of bytes.
+
+ size_t chunk_bytes = 0;
+
+ currp = (MALLOC_HEADER *)
+ this->memory_pool_.acquire (nunits * sizeof (MALLOC_HEADER),
+ chunk_bytes);
+ if (currp != 0)
+ {
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nchunks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+
+ MALLOC_HEADER::init_ptr (&currp->next_block_,
+ 0,
+ this->cb_ptr_);
+ // Compute the chunk size in MALLOC_HEADER units.
+ currp->size_ = chunk_bytes / sizeof (MALLOC_HEADER);
+
+ // Insert the newly allocated chunk of memory into the
+ // free list. Add "1" to skip over the
+ // <MALLOC_HEADER> when freeing the pointer since
+ // the first thing <free> does is decrement by this
+ // amount.
+ this->shared_free (currp + 1);
+ currp = this->cb_ptr_->freep_;
+ }
+ else
+ return 0;
+ // Shouldn't do this here because of errors with the wchar ver
+ // This is because ACE_ERROR_RETURN converts the __FILE__ to
+ // wchar before printing out. The compiler will complain
+ // about this since a destructor would present in a SEH block
+ //ACE_ERROR_RETURN ((LM_ERROR,
+ // ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ // ACE_LIB_TEXT ("malloc")),
+ // 0);
+ }
+ prevp = currp;
+ currp = currp->next_block_;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+ }
+ ACE_NOTREACHED (return 0;)
+}
+
+// General-purpose memory allocator.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::malloc (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::malloc");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, 0);
+
+ return this->shared_malloc (nbytes);
+}
+
+// General-purpose memory allocator.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc (size_t nbytes,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc");
+ void *ptr = this->malloc (nbytes);
+
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, nbytes);
+
+ return ptr;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc");
+
+ return this->calloc (n_elem * elem_size, initial_value);
+}
+
+// Put block AP in the free list (must be called with locks held!)
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_free (void *ap)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_free");
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (ap == 0 || this->cb_ptr_ == 0)
+ return;
+
+
+ // Adjust AP to point to the block MALLOC_HEADER
+ MALLOC_HEADER *blockp = ((MALLOC_HEADER *) ap) - 1;
+ MALLOC_HEADER *currp = this->cb_ptr_->freep_;
+
+ // Search until we find the location where the blocks belongs. Note
+ // that addresses are kept in sorted order.
+
+ ACE_SEH_TRY
+ {
+ for (;
+ blockp <= currp
+ || blockp >= (MALLOC_HEADER *) currp->next_block_;
+ currp = currp->next_block_)
+ {
+ if (currp >= (MALLOC_HEADER *) currp->next_block_
+ && (blockp > currp
+ || blockp < (MALLOC_HEADER *) currp->next_block_))
+ // Freed block at the start or the end of the memory pool.
+ break;
+ }
+
+ // Join to upper neighbor.
+ if ((blockp + blockp->size_) == currp->next_block_)
+ {
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.nblocks_);
+ blockp->size_ += currp->next_block_->size_;
+ blockp->next_block_ = currp->next_block_->next_block_;
+ }
+ else
+ blockp->next_block_ = currp->next_block_;
+
+ // Join to lower neighbor.
+ if ((currp + currp->size_) == blockp)
+ {
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.nblocks_);
+ currp->size_ += blockp->size_;
+ currp->next_block_ = blockp->next_block_;
+ }
+ else
+ currp->next_block_ = blockp;
+
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.ninuse_);
+ this->cb_ptr_->freep_ = currp;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+}
+
+// No locks held here, caller must acquire/release lock.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void*
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_find (const char *name)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_find");
+#endif /* !ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (this->cb_ptr_ == 0)
+ return 0;
+
+ ACE_SEH_TRY
+ {
+ for (NAME_NODE *node = this->cb_ptr_->name_head_;
+ node != 0;
+ node = node->next_)
+ if (ACE_OS::strcmp (node->name (),
+ name) == 0)
+ return node;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_bind (const char *name,
+ void *pointer)
+{
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ // Combine the two allocations into one to avoid overhead...
+ NAME_NODE *new_node = 0;
+
+ ACE_ALLOCATOR_RETURN (new_node,
+ (NAME_NODE *)
+ this->shared_malloc (sizeof (NAME_NODE) +
+ ACE_OS::strlen (name) + 1),
+ -1);
+ char *name_ptr = (char *) (new_node + 1);
+
+ // Use operator placement new to insert <new_node> at the head of
+ // the linked list of <NAME_NODE>s.
+ NAME_NODE *result =
+ new (new_node) NAME_NODE (name,
+ name_ptr,
+ ACE_reinterpret_cast (char *,
+ pointer),
+ this->cb_ptr_->name_head_);
+ this->cb_ptr_->name_head_ = result;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::trybind (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::trybind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ NAME_NODE *node = (NAME_NODE *) this->shared_find (name);
+
+ if (node == 0)
+ // Didn't find it, so insert it.
+ return this->shared_bind (name, pointer);
+
+ // Found it, so return a copy of the current entry.
+ pointer = (char *) node->pointer_;
+ return 1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::bind (const char *name,
+ void *pointer,
+ int duplicates)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::bind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ if (duplicates == 0 && this->shared_find (name) != 0)
+ // If we're not allowing duplicates, then if the name is already
+ // present, return 1.
+ return 1;
+
+ // If we get this far, either we're allowing duplicates or we didn't
+ // find the name yet.
+ return this->shared_bind (name, pointer);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find");
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ NAME_NODE *node = (NAME_NODE *) this->shared_find (name);
+
+ if (node == 0)
+ return -1;
+
+ pointer = (char *) node->pointer_;
+ return 0;
+}
+
+// Returns a count of the number of available chunks that can hold
+// <size> byte allocations. Function can be used to determine if you
+// have reached a water mark. This implies a fixed amount of allocated
+// memory.
+//
+// @param size - the chunk size of that you would like a count of
+// @return function returns the number of chunks of the given size
+// that would fit in the currently allocated memory
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ssize_t
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::avail_chunks (size_t size) const
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::avail_chunks");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_, -1);
+
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ size_t count = 0;
+ // Avoid dividing by 0...
+ size = size == 0 ? 1 : size;
+ MALLOC_HEADER *currp = this->cb_ptr_->freep_;
+
+ // Calculate how many will fit in this block.
+ do {
+ size_t avail_size = currp->size_ == 0 ? 0 : currp->size_ - 1;
+ if (avail_size * sizeof (MALLOC_HEADER) >= size)
+ count += avail_size * sizeof (MALLOC_HEADER) / size;
+ currp = currp->next_block_;
+ }
+ while (currp != this->cb_ptr_->freep_);
+
+ return count;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find (const char *name)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ return this->shared_find (name) == 0 ? -1 : 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind (const char *name, void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
+
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ NAME_NODE *prev = 0;
+
+ for (NAME_NODE *curr = this->cb_ptr_->name_head_;
+ curr != 0;
+ curr = curr->next_)
+ {
+ if (ACE_OS::strcmp (curr->name (), name) == 0)
+ {
+ pointer = (char *) curr->pointer_;
+
+ if (prev == 0)
+ this->cb_ptr_->name_head_ = curr->next_;
+ else
+ prev->next_ = curr->next_;
+
+ if (curr->next_)
+ curr->next_->prev_ = prev;
+
+ // This will free up both the node and the name due to our
+ // clever trick in <bind>!
+ this->shared_free (curr);
+ return 0;
+ }
+ prev = curr;
+ }
+
+ // Didn't find it, so fail.
+ return -1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind (const char *name)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind");
+ void *temp = 0;
+ return this->unbind (name, temp);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->curr_->dump ();
+ this->guard_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("name_ = %s"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_LIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name)
+ : malloc_ (malloc),
+ curr_ (0),
+ guard_ (malloc_.lock_),
+ name_ (name != 0 ? ACE_OS::strdup (name) : 0)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_LIFO_Iterator_T");
+ // Cheap trick to make code simple.
+ // @@ Doug, this looks like trouble...
+ NAME_NODE temp;
+ this->curr_ = &temp;
+ this->curr_->next_ = malloc_.cb_ptr_->name_head_;
+
+ this->advance ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_LIFO_Iterator_T (void)
+{
+ ACE_OS::free ((void *) this->name_);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry,
+ const char *&name)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = (char *) this->curr_->pointer_;
+ name = this->curr_->name ();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = this->curr_->pointer_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done (void) const
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done");
+
+ return this->curr_ == 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance (void)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance");
+
+ this->curr_ = this->curr_->next_;
+
+ if (this->name_ == 0)
+ return this->curr_ != 0;
+
+ while (this->curr_ != 0
+ && ACE_OS::strcmp (this->name_,
+ this->curr_->name ()) != 0)
+ this->curr_ = this->curr_->next_;
+
+ return this->curr_ != 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->curr_->dump ();
+ this->guard_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("name_ = %s"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_FIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name)
+ : malloc_ (malloc),
+ curr_ (0),
+ guard_ (malloc_.lock_),
+ name_ (name != 0 ? ACE_OS::strdup (name) : 0)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_FIFO_Iterator");
+ // Cheap trick to make code simple.
+ // @@ Doug, this looks like trouble...
+ NAME_NODE temp;
+ this->curr_ = &temp;
+ this->curr_->next_ = malloc_.cb_ptr_->name_head_;
+ this->curr_->prev_ = 0;
+
+ // Go to the first element that was inserted.
+ this->start ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_FIFO_Iterator_T (void)
+{
+ ACE_OS::free ((void *) this->name_);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry,
+ const char *&name)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = (char *) this->curr_->pointer_;
+ name = this->curr_->name ();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = this->curr_->pointer_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done (void) const
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done");
+
+ return this->curr_ == 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance (void)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance");
+
+ this->curr_ = this->curr_->prev_;
+
+ if (this->name_ == 0)
+ return this->curr_ != 0;
+
+ while (this->curr_ != 0
+ && ACE_OS::strcmp (this->name_,
+ this->curr_->name ()) != 0)
+ this->curr_ = this->curr_->prev_;
+
+ return this->curr_ != 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::start (void)
+{
+ this->curr_ = this->curr_->next_;
+ NAME_NODE *prev = 0;
+
+ // Locate the element that was inserted first.
+ // @@ We could optimize this by making the list a circular list or
+ // storing an extra pointer.
+ while (this->curr_ != 0)
+ {
+ prev = this->curr_;
+ this->curr_ = this->curr_->next_;
+ }
+
+ this->curr_ = prev;
+ return this->curr_ != 0;
+}
+
+#endif /* ACE_MALLOC_T_C */
diff --git a/ace/Memory/Malloc_T.h b/ace/Memory/Malloc_T.h
new file mode 100644
index 00000000000..bc8c42cd66f
--- /dev/null
+++ b/ace/Memory/Malloc_T.h
@@ -0,0 +1,730 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Malloc_T.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt and Irfan Pyarali
+ */
+//=============================================================================
+
+#ifndef ACE_MALLOC_T_H
+#define ACE_MALLOC_T_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/Malloc.h" /* Need ACE_Control_Block */
+#include "ace/Malloc_Allocator.h"
+#include "ace/Free_List.h"
+
+/**
+ * @class ACE_Cached_Mem_Pool_Node
+ *
+ * @brief <ACE_Cached_Mem_Pool_Node> keeps unused memory within a free
+ * list.
+ *
+ * The length of a piece of unused memory must be greater than
+ * sizeof (void*). This makes sense because we'll waste even
+ * more memory if we keep them in a separate data structure.
+ * This class should really be placed within the next class
+ * <ACE_Cached_Allocator>. But this can't be done due to C++
+ * compiler portability problems.
+ */
+template <class T>
+class ACE_Cached_Mem_Pool_Node
+{
+public:
+ /// return the address of free memory.
+ T *addr (void);
+
+ /// get the next ACE_Cached_Mem_Pool_Node in a list.
+ ACE_Cached_Mem_Pool_Node<T> *get_next (void);
+
+ /// set the next ACE_Cached_Mem_Pool_Node.
+ void set_next (ACE_Cached_Mem_Pool_Node<T> *ptr);
+
+private:
+ /**
+ * Since memory is not used when placed in a free list,
+ * we can use it to maintain the structure of free list.
+ * I was using union to hide the fact of overlapping memory
+ * usage. However, that cause problem on MSVC. So, I now turn
+ * back to hack this with casting.
+ */
+ ACE_Cached_Mem_Pool_Node<T> *next_;
+};
+
+/**
+ * @class ACE_Cached_Allocator
+ *
+ * @brief Create a cached memory poll with <n_chunks> chunks each with
+ * sizeof (TYPE) size.
+ *
+ * This class enables caching of dynamically allocated,
+ * fixed-sized classes. Notice that the <code>sizeof (TYPE)</code>
+ * must be greater than or equal to <code> sizeof (void*) </code> for
+ * this to work properly.
+ *
+ * @sa ACE_Cached_Mem_Pool_Node
+ */
+template <class T, class ACE_LOCK>
+class ACE_Cached_Allocator : public ACE_New_Allocator
+{
+public:
+ /// Create a cached memory poll with <n_chunks> chunks
+ /// each with sizeof (TYPE) size.
+ ACE_Cached_Allocator (size_t n_chunks);
+
+ /// clear things up.
+ ~ACE_Cached_Allocator (void);
+
+ /**
+ * Get a chunk of memory from free list cache. Note that <nbytes> is
+ * only checked to make sure that it's <= to sizeof T, and is
+ * otherwise ignored since <malloc> always returns a pointer to an
+ * item of sizeof (T).
+ */
+ void *malloc (size_t nbytes = sizeof (T));
+
+ /**
+ * Get a chunk of memory from free list cache, giving them
+ * <initial_value>. Note that <nbytes> is only checked to make sure
+ * that it's <= to sizeof T, and is otherwise ignored since <malloc>
+ * always returns a pointer to an item of sizeof (T).
+ */
+ virtual void *calloc (size_t nbytes,
+ char initial_value = '\0');
+
+ /// This method is a no-op and just returns 0 since the free list
+ /// only works with fixed sized entities.
+ virtual void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0');
+
+ /// Return a chunk of memory back to free list cache.
+ void free (void *);
+
+private:
+ /// Remember how we allocate the memory in the first place so
+ /// we can clear things up later.
+ char *pool_;
+
+ /// Maintain a cached memory free list.
+ ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<T>, ACE_LOCK> free_list_;
+};
+
+/**
+ * @class ACE_Allocator_Adapter
+ *
+ * @brief This class is an Adapter that allows the <ACE_Allocator> to
+ * use the <Malloc> class below.
+ */
+template <class MALLOC>
+class ACE_Allocator_Adapter : public ACE_Allocator
+{
+public:
+ // Trait.
+ typedef MALLOC ALLOCATOR;
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+ // The following code will break C++ compilers that don't support
+ // template typedefs correctly.
+ typedef const ACE_TYPENAME MALLOC::MEMORY_POOL_OPTIONS *MEMORY_POOL_OPTIONS;
+#else
+ typedef const void *MEMORY_POOL_OPTIONS;
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+ // = Initialization.
+ ACE_Allocator_Adapter (const char *pool_name = 0);
+
+ ACE_Allocator_Adapter (const char *pool_name,
+ const char *lock_name,
+ MEMORY_POOL_OPTIONS options = 0)
+ : allocator_ (ACE_TEXT_CHAR_TO_TCHAR (pool_name),
+ ACE_TEXT_CHAR_TO_TCHAR (lock_name),
+ options)
+ {
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+ }
+ // Constructor (this has to be inline to avoid bugs with some C++ compilers.
+
+#if defined (ACE_HAS_WCHAR)
+ ACE_Allocator_Adapter (const wchar_t *pool_name);
+
+ ACE_Allocator_Adapter (const wchar_t *pool_name,
+ const wchar_t *lock_name,
+ MEMORY_POOL_OPTIONS options = 0)
+ : allocator_ (ACE_TEXT_WCHAR_TO_TCHAR (pool_name),
+ ACE_TEXT_WCHAR_TO_TCHAR (lock_name),
+ options)
+ {
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+ }
+ // Constructor (this has to be inline to avoid bugs with some C++ compilers.
+#endif /* ACE_HAS_WCHAR */
+
+ /// Destructor.
+ virtual ~ACE_Allocator_Adapter (void);
+
+ // = Memory Management
+
+ /// Allocate <nbytes>, but don't give them any initial value.
+ virtual void *malloc (size_t nbytes);
+
+ /// Allocate <nbytes>, giving them all an <initial_value>.
+ virtual void *calloc (size_t nbytes, char initial_value = '\0');
+
+ /// Allocate <n_elem> each of size <elem_size>, giving them
+ /// <initial_value>.
+ virtual void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0');
+
+ /// Free <ptr> (must have been allocated by <ACE_Allocator::malloc>).
+ virtual void free (void *ptr);
+
+ /// Remove any resources associated with this memory manager.
+ virtual int remove (void);
+
+ // = Map manager like functions
+
+ /**
+ * Associate <name> with <pointer>. If <duplicates> == 0 then do
+ * not allow duplicate <name>/<pointer> associations, else if
+ * <duplicates> != 0 then allow duplicate <name>/<pointer>
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound <name> or (2) <duplicates> != 0, returns 1 if trying to
+ * bind a previously bound <name> and <duplicates> == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ virtual int bind (const char *name, void *pointer, int duplicates = 0);
+
+ /**
+ * Associate <name> with <pointer>. Does not allow duplicate
+ * <name>/<pointer> associations. Returns 0 if successfully binds
+ * (1) a previously unbound <name>, 1 if trying to bind a previously
+ * bound <name>, or returns -1 if a resource failure occurs. When
+ * this call returns <pointer>'s value will always reference the
+ * void * that <name> is associated with. Thus, if the caller needs
+ * to use <pointer> (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ virtual int trybind (const char *name, void *&pointer);
+
+ /// Locate <name> and pass out parameter via pointer. If found,
+ /// return 0, Returns -1 if <name> isn't found.
+ virtual int find (const char *name, void *&pointer);
+
+ /// Returns 0 if the name is in the mapping and -1 if not.
+ virtual int find (const char *name);
+
+ /// Unbind (remove) the name from the map. Don't return the pointer
+ /// to the caller
+ virtual int unbind (const char *name);
+
+ /// Break any association of name. Returns the value of pointer in
+ /// case the caller needs to deallocate memory.
+ virtual int unbind (const char *name, void *&pointer);
+
+ // = Protection and "sync" (i.e., flushing data to backing store).
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If <len> == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /// Returns the underlying allocator.
+ ALLOCATOR &alloc (void);
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ /// Dump statistics of how malloc is behaving.
+ virtual void print_stats (void) const;
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ /// Dump the state of the object.
+ virtual void dump (void) const;
+
+private:
+ /// ALLOCATOR instance, which is owned by the adapter.
+ ALLOCATOR allocator_;
+};
+
+/**
+ * @class ACE_Static_Allocator
+ *
+ * @brief Defines a class that provided a highly optimized memory
+ * management scheme for allocating memory statically.
+ *
+ * This class allocates a fixed-size <POOL_SIZE> of memory and
+ * uses the <ACE_Static_Allocator_Base> class implementations of
+ * <malloc> and <calloc> to optimize memory allocation from this
+ * pool.
+ */
+template <size_t POOL_SIZE>
+class ACE_Static_Allocator : public ACE_Static_Allocator_Base
+{
+public:
+ ACE_Static_Allocator (void)
+ : ACE_Static_Allocator_Base (pool_, POOL_SIZE)
+ {
+ // This function <{must}> be inlined!!!
+ }
+
+private:
+ /// Pool contents.
+ char pool_[POOL_SIZE];
+};
+
+// Forward declaration.
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+class ACE_Malloc_LIFO_Iterator_T;
+
+// Ensure backwards compatibility...
+#define ACE_Malloc_Iterator ACE_Malloc_LIFO_Iterator
+
+// Forward declaration.
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+class ACE_Malloc_FIFO_Iterator_T;
+
+/**
+ * @class ACE_Malloc_T
+ *
+ * @brief Define a C++ class that uses parameterized types to provide
+ * an extensible mechanism for encapsulating various of dynamic
+ * memory management strategies.
+ *
+ * This class can be configured flexibly with different
+ * MEMORY_POOL strategies and different types of ACE_LOCK
+ * strategies.
+ */
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+class ACE_Malloc_T
+{
+public:
+ friend class ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>;
+ friend class ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>;
+ typedef ACE_MEM_POOL MEMORY_POOL;
+ typedef ACE_MEM_POOL_OPTIONS MEMORY_POOL_OPTIONS;
+ typedef ACE_TYPENAME ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef ACE_TYPENAME ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization and termination methods.
+ /**
+ * Initialize ACE_Malloc. This constructor passes <pool_name> to
+ * initialize the memory pool, and uses <ACE::basename> to
+ * automatically extract out the name used for the underlying lock
+ * name (if necessary).
+ */
+ ACE_Malloc_T (const ACE_TCHAR *pool_name = 0);
+
+ /**
+ * Initialize ACE_Malloc. This constructor passes <pool_name> to
+ * initialize the memory pool, and uses <lock_name> to automatically
+ * extract out the name used for the underlying lock name (if
+ * necessary). In addition, <options> is passed through to
+ * initialize the underlying memory pool.
+ */
+ ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options = 0);
+
+#if !defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+ /// This is necessary to work around template bugs with certain C++
+ /// compilers.
+ ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const void *options = 0);
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+
+ /// Destructor
+ ~ACE_Malloc_T (void);
+
+ /// Get Reference counter.
+ int ref_counter (void);
+
+ /// Release ref counter.
+ int release (void);
+
+ /// Releases resources allocated by <ACE_Malloc>.
+ int remove (void);
+
+ // = Memory management
+
+ /// Allocate <nbytes>, but don't give them any initial value.
+ void *malloc (size_t nbytes);
+
+ /// Allocate <nbytes>, giving them <initial_value>.
+ void *calloc (size_t nbytes, char initial_value = '\0');
+
+ /// Allocate <n_elem> each of size <elem_size>, giving them
+ /// <initial_value>.
+ void *calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value = '\0');
+
+ /// Deallocate memory pointed to by <ptr>, which must have been
+ /// allocated previously by <this->malloc>.
+ void free (void *ptr);
+
+ /// Returns a reference to the underlying memory pool.
+ MEMORY_POOL &memory_pool (void);
+
+ // = Map manager like functions
+
+ /**
+ * Associate <name> with <pointer>. If <duplicates> == 0 then do
+ * not allow duplicate <name>/<pointer> associations, else if
+ * <duplicates> != 0 then allow duplicate <name>/<pointer>
+ * assocations. Returns 0 if successfully binds (1) a previously
+ * unbound <name> or (2) <duplicates> != 0, returns 1 if trying to
+ * bind a previously bound <name> and <duplicates> == 0, else
+ * returns -1 if a resource failure occurs.
+ */
+ int bind (const char *name, void *pointer, int duplicates = 0);
+
+ /**
+ * Associate <name> with <pointer>. Does not allow duplicate
+ * <name>/<pointer> associations. Returns 0 if successfully binds
+ * (1) a previously unbound <name>, 1 if trying to bind a previously
+ * bound <name>, or returns -1 if a resource failure occurs. When
+ * this call returns <pointer>'s value will always reference the
+ * void * that <name> is associated with. Thus, if the caller needs
+ * to use <pointer> (e.g., to free it) a copy must be maintained by
+ * the caller.
+ */
+ int trybind (const char *name, void *&pointer);
+
+ /// Locate <name> and pass out parameter via <pointer>. If found,
+ /// return 0, returns -1 if failure occurs.
+ int find (const char *name, void *&pointer);
+
+ /// Returns 0 if <name> is in the mapping. -1, otherwise.
+ int find (const char *name);
+
+ /**
+ * Unbind (remove) the name from the map. Don't return the pointer
+ * to the caller. If you want to remove all occurrences of <name>
+ * you'll need to call this method multiple times until it fails...
+ */
+ int unbind (const char *name);
+
+ /**
+ * Unbind (remove) one association of <name> to <pointer>. Returns
+ * the value of pointer in case the caller needs to deallocate
+ * memory. If you want to remove all occurrences of <name> you'll
+ * need to call this method multiple times until it fails...
+ */
+ int unbind (const char *name, void *&pointer);
+
+ // = Protection and "sync" (i.e., flushing data to backing store).
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If <len> == -1 then sync the
+ * whole region.
+ */
+ int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /**
+ * Returns a count of the number of available chunks that can hold
+ * <size> byte allocations. Function can be used to determine if you
+ * have reached a water mark. This implies a fixed amount of allocated
+ * memory.
+ *
+ * @param size - the chunk size of that you would like a count of
+ * @return function returns the number of chunks of the given size
+ * that would fit in the currently allocated memory.
+ */
+ ssize_t avail_chunks (size_t size) const;
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ /// Dump statistics of how malloc is behaving.
+ void print_stats (void) const;
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ /// Returns a pointer to the lock used to provide mutual exclusion to
+ /// an <ACE_Malloc> allocator.
+ ACE_LOCK &mutex (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Return cb_ptr value.
+ void *base_addr (void);
+
+private:
+ /// Initialize the Malloc pool.
+ int open (void);
+
+ /// Associate <name> with <pointer>. Assumes that locks are held by
+ /// callers.
+ int shared_bind (const char *name,
+ void *pointer);
+
+ /**
+ * Try to locate <name>. If found, return the associated
+ * <ACE_Name_Node>, else returns 0 if can't find the <name>.
+ * Assumes that locks are held by callers. Remember to cast the
+ * return value to ACE_CB::ACE_Name_Node*.
+ */
+ void *shared_find (const char *name);
+
+ /// Allocate memory. Assumes that locks are held by callers.
+ void *shared_malloc (size_t nbytes);
+
+ /// Deallocate memory. Assumes that locks are held by callers.
+ void shared_free (void *ptr);
+
+ /// Pointer to the control block that is stored in memory controlled
+ /// by <MEMORY_POOL>.
+ ACE_CB *cb_ptr_;
+
+ /// Pool of memory used by <ACE_Malloc> to manage its freestore.
+ MEMORY_POOL memory_pool_;
+
+ /// Lock that ensures mutual exclusion for the <MEMORY_POOL>.
+ ACE_LOCK lock_;
+};
+
+/**
+ * @class ACE_Malloc_LIFO_Iterator_T
+ *
+ * @brief LIFO iterator for names stored in Malloc'd memory.
+ *
+ * Does not support deletions while iteration is occurring.
+ */
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+class ACE_Malloc_LIFO_Iterator_T
+{
+public:
+ typedef ACE_TYPENAME ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef ACE_TYPENAME ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization method.
+ /// if <name> = 0 it will iterate through everything else only
+ /// through those entries whose <name> match.
+ ACE_Malloc_LIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name = 0);
+
+ ~ACE_Malloc_LIFO_Iterator_T (void);
+
+ // = Iteration methods.
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Pass back the next <entry> in the set that hasn't yet been
+ /// visited. Returns 0 when all items have been seen, else 1.
+ int next (void *&next_entry);
+
+ /**
+ * Pass back the next <entry> (and the <name> associated with it) in
+ * the set that hasn't yet been visited. Returns 0 when all items
+ * have been seen, else 1.
+ */
+ int next (void *&next_entry,
+ const char *&name);
+
+ /// Move forward by one element in the set. Returns 0 when all the
+ /// items in the set have been seen, else 1.
+ int advance (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Malloc we are iterating over.
+ ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc_;
+
+ /// Keeps track of how far we've advanced...
+ NAME_NODE *curr_;
+
+ /// Lock Malloc for the lifetime of the iterator.
+ ACE_Read_Guard<ACE_LOCK> guard_;
+
+ /// Name that we are searching for.
+ const char *name_;
+};
+
+/**
+ * @class ACE_Malloc_FIFO_Iterator_T
+ *
+ * @brief FIFO iterator for names stored in Malloc'd memory.
+ *
+ * Does not support deletions while iteration is occurring.
+ */
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+class ACE_Malloc_FIFO_Iterator_T
+{
+public:
+ typedef ACE_TYPENAME ACE_CB::ACE_Name_Node NAME_NODE;
+ typedef ACE_TYPENAME ACE_CB::ACE_Malloc_Header MALLOC_HEADER;
+
+ // = Initialization method.
+ /// if <name> = 0 it will iterate through everything else only
+ /// through those entries whose <name> match.
+ ACE_Malloc_FIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name = 0);
+
+ ~ACE_Malloc_FIFO_Iterator_T (void);
+
+ // = Iteration methods.
+
+ /// Returns 1 when all items have been seen, else 0.
+ int done (void) const;
+
+ /// Pass back the next <entry> in the set that hasn't yet been
+ /// visited. Returns 0 when all items have been seen, else 1.
+ int next (void *&next_entry);
+
+ /**
+ * Pass back the next <entry> (and the <name> associated with it) in
+ * the set that hasn't yet been visited. Returns 0 when all items
+ * have been seen, else 1.
+ */
+ int next (void *&next_entry,
+ const char *&name);
+
+ /// Move forward by one element in the set. Returns 0 when all the
+ /// items in the set have been seen, else 1.
+ int advance (void);
+
+ /// Go to the starting element that was inserted first. Returns 0
+ /// when there is no item in the set, else 1.
+ int start (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Malloc we are iterating over.
+ ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc_;
+
+ /// Keeps track of how far we've advanced...
+ NAME_NODE *curr_;
+
+ /// Lock Malloc for the lifetime of the iterator.
+ ACE_Read_Guard<ACE_LOCK> guard_;
+
+ /// Name that we are searching for.
+ const char *name_;
+};
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+class ACE_Malloc : public ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block>
+{
+public:
+ // = Initialization and termination methods.
+ /**
+ * Initialize ACE_Malloc. This constructor passes <pool_name> to
+ * initialize the memory pool, and uses <ACE::basename> to
+ * automatically extract out the name used for the underlying lock
+ * name (if necessary).
+ */
+ ACE_Malloc (const ACE_TCHAR *pool_name = 0);
+
+ /**
+ * Initialize ACE_Malloc. This constructor passes <pool_name> to
+ * initialize the memory pool, and uses <lock_name> to automatically
+ * extract out the name used for the underlying lock name (if
+ * necessary). In addition, <options> is passed through to
+ * initialize the underlying memory pool.
+ */
+ ACE_Malloc (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options = 0);
+
+#if !defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+ /// This is necessary to work around template bugs with certain C++
+ /// compilers.
+ ACE_Malloc (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const void *options = 0);
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
+};
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+class ACE_Malloc_LIFO_Iterator : public ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block>
+{
+public:
+ // = Initialization method.
+ /// if <name> = 0 it will iterate through everything else only
+ /// through those entries whose <name> match.
+ ACE_Malloc_LIFO_Iterator (ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK> &malloc,
+ const char *name = 0);
+};
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+class ACE_Malloc_FIFO_Iterator : public ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block>
+{
+public:
+ // = Initialization method.
+ /// if <name> = 0 it will iterate through everything else only
+ /// through those entries whose <name> match.
+ ACE_Malloc_FIFO_Iterator (ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK> &malloc,
+ const char *name = 0);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Malloc_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Malloc_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Malloc_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_MALLOC_H */
diff --git a/ace/Memory/Malloc_T.i b/ace/Memory/Malloc_T.i
new file mode 100644
index 00000000000..27e5f7ae4f8
--- /dev/null
+++ b/ace/Memory/Malloc_T.i
@@ -0,0 +1,296 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Malloc_T.i
+
+template <class T> ACE_INLINE T *
+ACE_Cached_Mem_Pool_Node<T>::addr (void)
+{
+ // This should be done using a single reinterpret_cast, but Sun/CC
+ // (4.2) gets awfully confused when T is a char[20] (and maybe other
+ // types).
+ return ACE_static_cast (T *, ACE_static_cast (void *, this));
+}
+
+template <class T> ACE_INLINE ACE_Cached_Mem_Pool_Node<T> *
+ACE_Cached_Mem_Pool_Node<T>::get_next (void)
+{
+ return this->next_;
+}
+
+template <class T> ACE_INLINE void
+ACE_Cached_Mem_Pool_Node<T>::set_next (ACE_Cached_Mem_Pool_Node<T> *ptr)
+{
+ this->next_ = ptr;
+}
+
+template <class T, class ACE_LOCK> ACE_INLINE void *
+ACE_Cached_Allocator<T, ACE_LOCK>::malloc (size_t nbytes)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > sizeof (T))
+ return NULL;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ return this->free_list_.remove ()->addr ();
+}
+
+template <class T, class ACE_LOCK> ACE_INLINE void *
+ACE_Cached_Allocator<T, ACE_LOCK>::calloc (size_t nbytes,
+ char initial_value)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > sizeof (T))
+ return NULL;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ void *ptr = this->free_list_.remove ()->addr ();
+ ACE_OS::memset (ptr, initial_value, sizeof (T));
+ return ptr;
+}
+
+template <class T, class ACE_LOCK> ACE_INLINE void *
+ACE_Cached_Allocator<T, ACE_LOCK>::calloc (size_t,
+ size_t,
+ char)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+template <class T, class ACE_LOCK> ACE_INLINE void
+ACE_Cached_Allocator<T, ACE_LOCK>::free (void * ptr)
+{
+ this->free_list_.add ((ACE_Cached_Mem_Pool_Node<T> *) ptr) ;
+}
+
+template <class MALLOC> ACE_INLINE void *
+ACE_Allocator_Adapter<MALLOC>::malloc (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::malloc");
+ return this->allocator_.malloc (nbytes);
+}
+
+template <class MALLOC> ACE_INLINE void *
+ACE_Allocator_Adapter<MALLOC>::calloc (size_t nbytes,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::calloc");
+ return this->allocator_.calloc (nbytes, initial_value);
+}
+
+template <class MALLOC> ACE_INLINE void *
+ACE_Allocator_Adapter<MALLOC>::calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::calloc");
+ return this->allocator_.calloc (n_elem, elem_size, initial_value);
+}
+
+template <class MALLOC> ACE_INLINE MALLOC &
+ACE_Allocator_Adapter<MALLOC>::alloc (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::allocator");
+ return this->allocator_;
+}
+
+template <class MALLOC> ACE_INLINE void
+ACE_Allocator_Adapter<MALLOC>::free (void *ptr)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::free");
+ this->allocator_.free (ptr);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::remove (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::remove");
+ return this->allocator_.remove ();
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::trybind (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::trybind");
+ return this->allocator_.trybind (name, pointer);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::bind (const char *name,
+ void *pointer,
+ int duplicates)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::bind");
+ return this->allocator_.bind (name, pointer, duplicates);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::find (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find");
+ return this->allocator_.find (name, pointer);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::find (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find");
+ return this->allocator_.find (name);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::unbind (const char *name, void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind");
+ return this->allocator_.unbind (name, pointer);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::unbind (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind");
+ return this->allocator_.unbind (name);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::sync (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::sync");
+ return this->allocator_.sync (len, flags);
+}
+
+template <class MALLOC> ACE_INLINE int
+ACE_Allocator_Adapter<MALLOC>::sync (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::sync");
+ return this->allocator_.sync (addr, len, flags);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ref_counter (void)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_, -1);
+ if (this->cb_ptr_ != 0)
+ return this->cb_ptr_->ref_counter_;
+
+ return -1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::release (void)
+{
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, (ACE_LOCK &) this->lock_, -1);
+ if (this->cb_ptr_ != 0)
+ return --this->cb_ptr_->ref_counter_;
+
+ return -1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE ACE_MEM_POOL &
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::memory_pool (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEMORY_POOL, ACE_LOCK, ACE_CB>::memory_pool");
+ return this->memory_pool_;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::sync (ssize_t len,
+ int flags)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEMORY_POOL, ACE_LOCK, ACE_CB>::sync");
+ return this->memory_pool_.sync (len, flags);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::sync (void *addr,
+ size_t len,
+ int flags)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEMORY_POOL, ACE_LOCK, ACE_CB>::sync");
+ return this->memory_pool_.sync (addr, len, flags);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::protect (ssize_t len,
+ int flags)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEMORY_POOL, ACE_LOCK, ACE_CB>::protect");
+ return this->memory_pool_.protect (len, flags);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::protect (void *addr,
+ size_t len,
+ int flags)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEMORY_POOL, ACE_LOCK, ACE_CB>::protect");
+ return this->memory_pool_.protect (addr, len, flags);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE ACE_LOCK &
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::mutex (void)
+{
+ return this->lock_;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::base_addr (void)
+{
+ return this->cb_ptr_;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> ACE_INLINE
+ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Malloc (const ACE_TCHAR *pool_name)
+ : ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block> (pool_name)
+{
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> ACE_INLINE
+ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Malloc (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options)
+ : ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block> (pool_name, lock_name, options)
+{
+}
+
+#if !defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+template <ACE_MEM_POOL_1, class ACE_LOCK> ACE_INLINE
+ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Malloc (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const void *options)
+ : ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block> (pool_name, lock_name, options)
+{
+}
+#endif /* !ACE_HAS_TEMPLATE_TYPEDEFS */
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> ACE_INLINE
+ACE_Malloc_LIFO_Iterator<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Malloc_LIFO_Iterator (ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK> &malloc,
+ const char *name)
+ : ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block> (malloc, name)
+{
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> ACE_INLINE
+ACE_Malloc_FIFO_Iterator<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Malloc_FIFO_Iterator (ACE_Malloc<ACE_MEM_POOL_2, ACE_LOCK> &malloc,
+ const char *name)
+ : ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_Control_Block> (malloc, name)
+{
+}
+
+
+
+#if 0
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::init_malloc_header_ptr (void* ptr)
+{
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ new (ptr) ACE_MALLOC_HEADER_PTR (this->cb_ptr_, 0);
+#else
+ ACE_UNUSED_ARG (ptr);
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+}
+#endif
diff --git a/ace/Memory/Mem_Map.cpp b/ace/Memory/Mem_Map.cpp
new file mode 100644
index 00000000000..4953fcef78d
--- /dev/null
+++ b/ace/Memory/Mem_Map.cpp
@@ -0,0 +1,386 @@
+// $Id$
+
+// Defines the member functions for the memory mapping facility.
+
+#include "ace/Mem_Map.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_WIN32) \
+ && (!defined(ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0))
+# define ACE_USE_MAPPING_NAME 1
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_USE_MAPPING_NAME)
+#include "ace/SString.h"
+#endif /* ACE_USE_MAPPING_NAME */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Mem_Map.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Mem_Map, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Mem_Map)
+
+#if defined (ACE_USE_MAPPING_NAME)
+// Gets a mapping object name from a file name. TODO: The file name
+// is used as the key to the mapping. We should try to avoid mapping
+// the same object name to different files (there is a mapping object
+// name length limitation).
+
+static void
+to_mapping_name (ACE_TCHAR *mapobjname,
+ const ACE_TCHAR *filename,
+ size_t len)
+{
+ --len;
+ size_t i = 0;
+
+ while (*filename && i < len)
+ {
+ if (*filename == ACE_LIB_TEXT ('\\'))
+ // Can't use backslash in mapping object name.
+ mapobjname[i] = ACE_LIB_TEXT ('.');
+ else
+ mapobjname[i] = *filename;
+ ++filename;
+ ++i;
+ }
+
+ mapobjname[i] = 0;
+}
+#endif /* ACE_USE_MAPPING_NAME */
+
+void
+ACE_Mem_Map::dump (void) const
+{
+ ACE_TRACE ("ACE_Mem_Map::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("base_addr_ = %x"), this->base_addr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfilename_ = %s"), this->filename_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlength_ = %d"), this->length_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhandle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfile_mapping_ = %d"), this->file_mapping_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nclose_handle_ = %d"), this->close_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+int
+ACE_Mem_Map::close (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::close");
+
+ this->unmap ();
+
+ return this->close_handle ();
+}
+
+ACE_Mem_Map::~ACE_Mem_Map (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::~ACE_Mem_Map");
+
+ this->close ();
+}
+
+// This function does the dirty work of actually calling ACE_OS::mmap
+// to map the file into memory.
+
+int
+ACE_Mem_Map::map_it (ACE_HANDLE handle,
+ int length_request,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map_it");
+
+#if defined (ACE_LACKS_AUTO_MMAP_REPLACEMENT)
+ // If the system does not replace any previous mappings, then
+ // unmap() before (potentially) mapping to the same location.
+ int unmap_result = this->unmap ();
+ if (unmap_result != 0)
+ return unmap_result;
+#endif /* ACE_LACKS_AUTO_MMAP_REPLACEMENT */
+
+ this->base_addr_ = addr;
+ this->handle_ = handle;
+
+#if defined (CHORUS)
+ // Chorus does not support filesize on a shared memory handle. We
+ // assume that <length_> = 0 when <ACE_Mem_Map> is initially
+ // constructed (i.e., before <map_it> is called with a valid
+ // <len_request>).
+ long result = this->length_;
+
+ if (result == -1)
+ return -1;
+#else
+ long result = ACE_OS::filesize (this->handle_);
+#endif /* CHORUS */
+
+ // At this point we know <result> is not negative...
+ size_t current_file_length = ACE_static_cast (size_t, result);
+
+ // Flag to indicate if we need to extend the back store
+ int extend_backing_store = 0;
+
+ // File length requested by user
+ size_t requested_file_length = 0;
+
+ // Check <length_request>
+ if (length_request == -1)
+ // Set length to file_request.
+ this->length_ = current_file_length - offset;
+ else
+ {
+ // File length implicitly requested by user
+ requested_file_length = length_request + offset;
+
+ // Check to see if we need to extend the backing store
+ if (requested_file_length > current_file_length)
+ {
+ // If the length of the mapped region is less than the
+ // length of the file then we force a complete new remapping
+ // by setting the descriptor to ACE_INVALID_HANDLE (closing
+ // down the descriptor if necessary).
+ this->close_filemapping_handle ();
+
+ // Remember to extend the backing store
+ extend_backing_store = 1;
+ }
+
+ // Set length to length_request
+ this->length_ = length_request;
+ }
+
+ // Check if we need to extend the backing store.
+ if (extend_backing_store)
+ {
+#if !defined (CHORUS)
+ // Remember than write increases the size by one.
+ size_t null_byte_position;
+ if (requested_file_length > 0)
+ // This will make the file size <requested_file_length>
+ null_byte_position = requested_file_length - 1;
+ else
+ // This will make the file size 1
+ null_byte_position = 0;
+
+ if (ACE_OS::pwrite (this->handle_,
+ "",
+ 1,
+ null_byte_position) == -1)
+ return -1;
+#else
+ // This nonsense is to make this code similar to the above code.
+ size_t actual_file_length;
+ if (requested_file_length > 0)
+ // This will make the file size <requested_file_length>
+ actual_file_length = requested_file_length;
+ else
+ // This will make the file size 1
+ actual_file_length = 1;
+
+ if (ACE_OS::ftruncate (this->handle_,
+ actual_file_length) == -1)
+ return -1;
+#endif /* !CHORUS */
+ }
+
+#if defined (__Lynx__)
+ // Set flag that indicates whether PROT_WRITE has been enabled.
+ write_enabled_ = ACE_BIT_ENABLED (prot, PROT_WRITE);
+#endif /* __Lynx__ */
+
+#if defined (ACE_USE_MAPPING_NAME)
+ if (ACE_BIT_ENABLED (share, MAP_SHARED))
+ {
+# if defined(__MINGW32__)
+ const int max_mapping_name_length = 32;
+# else
+ const int max_mapping_name_length = 31;
+# endif /* __MINGW32__ */
+ ACE_TCHAR file_mapping_name[max_mapping_name_length + 1];
+ to_mapping_name (file_mapping_name,
+ filename_,
+ max_mapping_name_length + 1);
+
+ this->base_addr_ = ACE_OS::mmap (this->base_addr_,
+ this->length_,
+ prot,
+ share,
+ this->handle_,
+ offset,
+ &this->file_mapping_,
+ sa,
+ file_mapping_name);
+ }
+ else
+#endif /* ACE_USE_MAPPING_NAME */
+ this->base_addr_ = ACE_OS::mmap (this->base_addr_,
+ this->length_,
+ prot,
+ share,
+ this->handle_,
+ offset,
+ &this->file_mapping_,
+ sa);
+
+ return this->base_addr_ == MAP_FAILED ? -1 : 0;
+}
+
+int
+ACE_Mem_Map::open (const ACE_TCHAR *file_name,
+ int flags,
+ int mode,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::open");
+
+ ACE_OS::strsncpy (this->filename_,
+ file_name,
+ MAXPATHLEN);
+
+#if defined (CHORUS)
+ this->handle_ = ACE_OS::shm_open (file_name, flags, mode, sa);
+#else
+ this->handle_ = ACE_OS::open (file_name, flags, mode, sa);
+#endif /* CHORUS */
+
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+ else
+ {
+ this->close_handle_ = 1;
+ return 0;
+ }
+}
+
+int
+ACE_Mem_Map::map (const ACE_TCHAR *file_name,
+ int len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map");
+ this->length_ = 0;
+
+ if (this->open (file_name,
+ flags,
+ mode,
+ sa) == -1)
+ return -1;
+ else
+ return this->map_it (this->handle (),
+ len,
+ prot,
+ share,
+ addr,
+ offset,
+ sa);
+}
+
+ACE_Mem_Map::ACE_Mem_Map (void)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (0)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+ ACE_OS::memset (this->filename_, 0, sizeof this->filename_);
+}
+
+// Map a file specified by FILE_NAME.
+
+ACE_Mem_Map::ACE_Mem_Map (const ACE_TCHAR *file_name,
+ int len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (0)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+ if (this->map (file_name,
+ len,
+ flags,
+ mode,
+ prot,
+ share,
+ addr,
+ offset,
+ sa) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Mem_Map::ACE_Mem_Map")));
+}
+
+// Map a file from an open file descriptor HANDLE. This function will
+// lookup the length of the file if it is not given.
+
+ACE_Mem_Map::ACE_Mem_Map (ACE_HANDLE handle,
+ int len,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (0)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+
+ ACE_OS::memset (this->filename_,
+ 0,
+ sizeof this->filename_);
+ if (this->map (handle,
+ len,
+ prot,
+ share,
+ addr,
+ offset,
+ sa) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Mem_Map::ACE_Mem_Map")));
+}
+
+// Close down and remove the file from the file system.
+
+int
+ACE_Mem_Map::remove (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::remove");
+
+ ACE_OS::ftruncate (this->handle_, 0);
+ this->close ();
+
+ if (this->filename_[0] != '\0')
+#if defined (CHORUS)
+ return ACE_OS::shm_unlink (this->filename_);
+#else
+ return ACE_OS::unlink (this->filename_);
+#endif /* CHORUS */
+
+ else
+ return 0;
+}
diff --git a/ace/Memory/Mem_Map.h b/ace/Memory/Mem_Map.h
new file mode 100644
index 00000000000..8a0927fc418
--- /dev/null
+++ b/ace/Memory/Mem_Map.h
@@ -0,0 +1,214 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Mem_Map.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_MEM_MAP_H
+#define ACE_MEM_MAP_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Mem_Map
+ *
+ * @brief C++ interface OS memory mapping system call.
+ *
+ * This class works with both the mmap(2) UNIX system and the
+ * Win32 family of memory mapping system calls.
+ */
+class ACE_Export ACE_Mem_Map
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Default constructor.
+ ACE_Mem_Map (void);
+
+ /// Map a file from an open file descriptor <handle>. This function
+ /// will lookup the length of the file if it is not given.
+ ACE_Mem_Map (ACE_HANDLE handle,
+ int length = -1,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file specified by <file_name>.
+ ACE_Mem_Map (const ACE_TCHAR *filename,
+ int len = -1,
+ int flags = O_RDWR | O_CREAT,
+ int mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file from an open file descriptor <handle>. This function
+ /// will lookup the length of the file if it is not given.
+ int map (ACE_HANDLE handle,
+ int length = -1,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Remap the file associated with <handle_>.
+ int map (int length = -1,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Map a file specified by <filename>.
+ int map (const ACE_TCHAR *filename,
+ int len = -1,
+ int flags = O_RDWR | O_CREAT,
+ int mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Destructor.
+ ~ACE_Mem_Map (void);
+
+ /// Open the file without mapping it.
+ int open (const ACE_TCHAR *filename,
+ int flags = O_RDWR | O_CREAT,
+ int mode = ACE_DEFAULT_FILE_PERMS,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Close down the <handle_> if necessary and unmap the mapping.
+ int close (void);
+
+ /// Close down the <handle_> if necessary.
+ int close_handle (void);
+
+ /**
+ * Close down the internal <file_mapping_> if necessary. This is
+ * mostly necessary on Win32, which has a different handle for
+ * file-mapping kernel object.
+ */
+ int close_filemapping_handle (void);
+
+ /// This operator passes back the starting address of the mapped
+ /// file.
+ int operator () (void *&addr);
+
+ /// Return the base address.
+ void *addr (void) const;
+
+ /// This function returns the number of bytes currently mapped in the
+ /// file.
+ size_t size (void) const;
+
+ /// Unmap the region starting at <base_addr_>.
+ int unmap (int len = -1);
+
+ /// Unmap the region starting at <addr_>.
+ int unmap (void *addr, int len);
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <base_addr_>. If <len> == -1 then sync the whole
+ * region.
+ */
+ int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <base_addr_> up to <len> bytes. If <len> == -1 then
+ * change protection of all pages in the mapped region.
+ */
+ int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /// Close and remove the file from the file system.
+ int remove (void);
+
+ /// Hook into the underlying VM system.
+ int advise (int behavior, int len = -1);
+
+ /// Return the underlying <handle_>.
+ ACE_HANDLE handle (void) const;
+
+ /// Return the name of file that is mapped (if any).
+ const ACE_TCHAR *filename (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Base address of the memory-mapped file.
+ void *base_addr_;
+
+ /// Name of the file that is mapped.
+ ACE_TCHAR filename_[MAXPATHLEN + 1];
+
+ /// Length of the mapping.
+ size_t length_;
+
+ /// HANDLE for the open file.
+ ACE_HANDLE handle_;
+
+ /// HANDLE for the open mapping.
+ ACE_HANDLE file_mapping_;
+
+#if defined (__Lynx__)
+ /// Flag to indicate that PROT_WRITE has been enabled.
+ int write_enabled_;
+#endif /* __Lynx__ */
+
+ /// Keeps track of whether we need to close the handle. This is set
+ /// if we opened the file.
+ int close_handle_;
+
+ /// This method does the dirty work of actually calling ::mmap to map
+ /// the file into memory.
+ int map_it (ACE_HANDLE handle,
+ int len = -1,
+ int prot = PROT_RDWR,
+ int share = MAP_SHARED,
+ void *addr = 0,
+ off_t offset = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ // = Disallow copying and assignment.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Mem_Map (const ACE_Mem_Map &))
+ ACE_UNIMPLEMENTED_FUNC (void operator = (const ACE_Mem_Map &))
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Mem_Map.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_MEM_MAP_H */
diff --git a/ace/Memory/Mem_Map.i b/ace/Memory/Mem_Map.i
new file mode 100644
index 00000000000..7448fcb4933
--- /dev/null
+++ b/ace/Memory/Mem_Map.i
@@ -0,0 +1,251 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE ACE_HANDLE
+ACE_Mem_Map::handle (void) const
+{
+ ACE_TRACE ("ACE_Mem_Map::handle");
+ return this->handle_;
+}
+
+// Return the name of file that is mapped (if any).
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Mem_Map::filename (void) const
+{
+ return this->filename_;
+}
+
+ACE_INLINE int
+ACE_Mem_Map::map (ACE_HANDLE handle,
+ int len,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map");
+ return this->map_it (handle, len, prot, share, addr, offset, sa);
+}
+
+// Remap the file associated with <this->handle_>.
+
+ACE_INLINE int
+ACE_Mem_Map::map (int len,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map");
+ // If we're already mapped at a particular location then try to
+ // remap the file using the same base address.
+ if (addr == 0 && this->base_addr_ != 0 && this->base_addr_ != MAP_FAILED)
+ {
+ share |= MAP_FIXED;
+ addr = this->base_addr_;
+ }
+ return this->map_it (this->handle (), len, prot,
+ share, addr, offset, sa);
+}
+
+// This operator passes back the starting address of the mapped file.
+
+ACE_INLINE int
+ACE_Mem_Map::operator () (void *&addr)
+{
+ ACE_TRACE ("ACE_Mem_Map::operator");
+
+ if (this->base_addr_ == MAP_FAILED)
+ return -1;
+ else
+ {
+ addr = this->base_addr_;
+ return 0;
+ }
+}
+
+// Return the base address.
+
+ACE_INLINE void *
+ACE_Mem_Map::addr (void) const
+{
+ ACE_TRACE ("ACE_Mem_Map::addr");
+
+ return this->base_addr_;
+}
+
+// This function returns the number of bytes currently mapped in the
+// file.
+
+ACE_INLINE size_t
+ACE_Mem_Map::size (void) const
+{
+ ACE_TRACE ("ACE_Mem_Map::size");
+ return this->length_;
+}
+
+ACE_INLINE int
+ACE_Mem_Map::close_filemapping_handle (void)
+{
+ int result = 0;
+
+ if (this->file_mapping_ != this->handle_
+ && this->file_mapping_ != ACE_INVALID_HANDLE)
+ {
+ // On LynxOS, this will result in unlinking of the (hidden)
+ // shared memory file if there are no more references to it.
+ result = ACE_OS::close (this->file_mapping_);
+ this->file_mapping_ = ACE_INVALID_HANDLE;
+ }
+
+ return result;
+}
+
+// Unmap the region starting at <this->base_addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::unmap (int len)
+{
+ ACE_TRACE ("ACE_Mem_Map::unmap");
+
+ this->close_filemapping_handle ();
+
+#if defined (__Lynx__)
+ int writeback_result = 0;
+ if (write_enabled_)
+ {
+ // Write back the contents of the shared memory object to the
+ // file.
+ const off_t filesize = ACE_OS::filesize (handle_);
+ writeback_result =
+ ACE_OS::lseek (handle_, 0, 0) != -1
+ && ACE_OS::write (handle_,
+ base_addr_,
+ (int) filesize) == filesize ? 0 : -1;
+ }
+#endif /* __Lynx__ */
+ if (this->base_addr_ != MAP_FAILED)
+ {
+ int result = ACE_OS::munmap (this->base_addr_,
+ len < 0 ? this->length_ : len);
+ this->base_addr_ = MAP_FAILED;
+ return result;
+ }
+ else
+#if defined (__Lynx__)
+ return writeback_result;
+#else /* ! __Lynx__ */
+ return 0;
+#endif /* ! __Lynx__ */
+}
+
+// Unmap the region starting at <addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::unmap (void *addr, int len)
+{
+ ACE_TRACE ("ACE_Mem_Map::unmap");
+
+ this->close_filemapping_handle ();
+
+#if defined (__Lynx__)
+ int writeback_result = 0;
+ if (write_enabled_)
+ {
+ // Write back the contents of the shared memory object to the file.
+ const off_t filesize = ACE_OS::filesize (handle_);
+ writeback_result =
+ ACE_OS::lseek (handle_, 0, 0) != -1
+ && ACE_OS::write (handle_,
+ base_addr_,
+ (int) filesize) == filesize ? 0 : -1;
+ }
+#endif /* __Lynx__ */
+
+#if defined (__Lynx__)
+ return ACE_OS::munmap (addr,
+ len < 0 ? this->length_ : len)
+ | writeback_result;;
+#else /* ! __Lynx__ */
+ return ACE_OS::munmap (addr,
+ len < 0 ? this->length_ : len);
+#endif /* ! __Lynx__ */
+}
+
+// Sync <len> bytes of the memory region to the backing store starting
+// at <this->base_addr_>. If <len> == -1 then sync the whole mapped
+// region.
+
+ACE_INLINE int
+ACE_Mem_Map::sync (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_Mem_Map::sync");
+ return ACE_OS::msync (this->base_addr_,
+ len < 0 ? this->length_ : len,
+ flags);
+}
+
+// Sync <len> bytes of the memory region to the backing store starting
+// at <addr_>.
+
+ACE_INLINE int
+ACE_Mem_Map::sync (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Mem_Map::sync");
+ return ACE_OS::msync (addr, len, flags);
+}
+
+// Change the protection of the pages of the mapped region to <prot>
+// starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+// then change protection of all pages in the mapped region.
+
+ACE_INLINE int
+ACE_Mem_Map::protect (ssize_t len, int prot)
+{
+ ACE_TRACE ("ACE_Mem_Map::protect");
+ if (len < 0)
+ len = this->length_;
+ return ACE_OS::mprotect (this->base_addr_, len, prot);
+}
+
+// Change the protection of the pages of the mapped region to <prot>
+// starting at <addr> up to <len> bytes.
+
+ACE_INLINE int
+ACE_Mem_Map::protect (void *addr, size_t len, int prot)
+{
+ ACE_TRACE ("ACE_Mem_Map::protect");
+ return ACE_OS::mprotect (addr, len, prot);
+}
+
+// Hook into the underlying VM system.
+
+ACE_INLINE int
+ACE_Mem_Map::advise (int behavior, int len)
+{
+ ACE_TRACE ("ACE_Mem_Map::advise");
+ if (len < 0)
+ len = this->length_;
+
+ return ACE_OS::madvise ((caddr_t) this->base_addr_,
+ len,
+ behavior);
+}
+
+ACE_INLINE int
+ACE_Mem_Map::close_handle (void)
+{
+ int result = 0;
+
+ if (this->close_handle_)
+ {
+ this->close_handle_ = 0;
+ result = ACE_OS::close (this->handle_);
+ this->handle_ = ACE_INVALID_HANDLE;
+ }
+
+ return result;
+}
diff --git a/ace/Memory/Memory_Pool.cpp b/ace/Memory/Memory_Pool.cpp
new file mode 100644
index 00000000000..5a0fe63fabe
--- /dev/null
+++ b/ace/Memory/Memory_Pool.cpp
@@ -0,0 +1,1324 @@
+// $Id$
+
+// Memory_Pool.cpp
+#include "ace/Memory_Pool.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Memory_Pool.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Auto_Ptr.h"
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+#include "ace/Based_Pointer_T.h"
+#include "ace/Based_Pointer_Repository.h"
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ACE_RCSID(ace, Memory_Pool, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool)
+
+void
+ACE_Local_Memory_Pool::dump (void) const
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::dump");
+}
+
+ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const ACE_TCHAR *,
+ const OPTIONS *)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool");
+}
+
+void *
+ACE_Local_Memory_Pool::acquire (size_t nbytes,
+ size_t &rounded_bytes)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::acquire");
+ rounded_bytes = this->round_up (nbytes);
+
+ char *temp = 0;
+ ACE_NEW_RETURN (temp,
+ char[rounded_bytes],
+ 0);
+
+ ACE_Auto_Basic_Array_Ptr<char> cp (temp);
+
+ if (this->allocated_chunks_.insert (cp.get ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) insertion into set failed\n")),
+ 0);
+
+ return cp.release ();
+}
+
+int
+ACE_Local_Memory_Pool::release (void)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::release");
+
+ // Zap the memory we allocated.
+ for (ACE_Unbounded_Set<char *>::iterator i = this->allocated_chunks_.begin ();
+ i != this->allocated_chunks_.end ();
+ ++i)
+ delete [] *i;
+ this->allocated_chunks_.reset ();
+ return 0;
+}
+
+#if defined (ACE_WIN32)
+int
+ACE_Local_Memory_Pool::seh_selector (void *)
+{
+ return 0;
+ // Continue propagate the structural exception up.
+}
+#endif /* ACE_WIN32 */
+
+int
+ACE_Local_Memory_Pool::remap (void *)
+{
+ return 0;
+ // Not much can be done.
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool)
+
+void
+ACE_MMAP_Memory_Pool::dump (void) const
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::dump");
+}
+
+int
+ACE_MMAP_Memory_Pool::release (void)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::release");
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ());
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ this->mmap_.remove ();
+ return 0;
+}
+
+int
+ACE_MMAP_Memory_Pool::sync (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
+
+ if (len < 0)
+ len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
+
+ return this->mmap_.sync (len, flags);
+}
+
+// Sync <len> bytes of the memory region to the backing store starting
+// at <addr_>.
+
+int
+ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
+ return ACE_OS::msync (addr, len, flags);
+}
+
+// Change the protection of the pages of the mapped region to <prot>
+// starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+// then change protection of all pages in the mapped region.
+
+int
+ACE_MMAP_Memory_Pool::protect (ssize_t len, int prot)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
+
+ if (len < 0)
+ len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
+
+ return this->mmap_.protect (len, prot);
+}
+
+// Change the protection of the pages of the mapped region to <prot>
+// starting at <addr> up to <len> bytes.
+
+int
+ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
+ return ACE_OS::mprotect (addr, len, prot);
+}
+
+ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
+ const OPTIONS *options)
+ : base_addr_ (0),
+ flags_ (MAP_SHARED),
+ write_each_page_ (0),
+ minimum_bytes_ (0),
+ sa_ (0)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool");
+
+#if (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32)
+ // For plaforms that give the faulting address.
+ guess_on_fault_ = 0;
+#else
+ // For plaforms that do NOT give the faulting address, let the
+ // options decide whether to guess or not.
+ if (options)
+ guess_on_fault_ = options->guess_on_fault_;
+ else
+ // If no options are specified, default to true.
+ guess_on_fault_ = 1;
+#endif
+
+ // Only change the defaults if <options> != 0.
+ if (options)
+ {
+ if (options->flags_ != 0)
+ this->flags_ = options->flags_;
+ if (options->use_fixed_addr_)
+ {
+ this->base_addr_ =
+ ACE_const_cast (void *, options->base_addr_);
+ ACE_SET_BITS (flags_, MAP_FIXED);
+ }
+ this->write_each_page_ = options->write_each_page_;
+ this->minimum_bytes_ = options->minimum_bytes_;
+ if (options->sa_ != 0)
+ this->sa_ = options->sa_;
+ }
+
+ if (backing_store_name == 0)
+ {
+ // Only create a new unique filename for the backing store file
+ // if the user didn't supply one...
+#if defined (ACE_DEFAULT_BACKING_STORE)
+ // Create a temporary file.
+ ACE_OS::strcpy (this->backing_store_name_,
+ ACE_DEFAULT_BACKING_STORE);
+#else /* ACE_DEFAULT_BACKING_STORE */
+ if (ACE_Lib_Find::get_temp_dir (this->backing_store_name_,
+ MAXPATHLEN - 17) == -1)
+ // -17 for ace-malloc-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Temporary path too long, ")
+ ACE_LIB_TEXT ("defaulting to current directory\n")));
+ this->backing_store_name_[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (this->backing_store_name_,
+ ACE_LIB_TEXT ("ace-malloc-XXXXXX"));
+
+#endif /* ACE_DEFAULT_BACKING_STORE */
+ }
+ else
+ ACE_OS::strsncpy (this->backing_store_name_,
+ backing_store_name,
+ (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
+
+#if !defined (ACE_WIN32) && !defined (CHORUS)
+ if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n", this->backing_store_name_));
+#endif /* ACE_WIN32 */
+}
+
+// Compute the new map_size of the backing store and commit the
+// memory.
+int
+ACE_MMAP_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
+ off_t &map_size)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name");
+
+#if defined (CHORUS)
+ map_size = rounded_bytes;
+#else
+ size_t seek_len;
+
+ if (this->write_each_page_)
+ // Write to the end of every block to ensure that we have enough
+ // space in the backing store.
+ seek_len = this->round_up (1); // round_up(1) is one page.
+ else
+ // We're willing to risk it all in the name of efficiency...
+ seek_len = rounded_bytes;
+
+ // The following loop will execute multiple times (if
+ // this->write_each_page == 1) or just once (if
+ // this->write_each_page == 0).
+
+ for (size_t cur_block = 0;
+ cur_block < rounded_bytes;
+ cur_block += seek_len)
+ {
+ map_size = ACE_OS::lseek (this->mmap_.handle (),
+ seek_len - 1,
+ SEEK_END);
+
+ if (map_size == -1
+ || ACE_OS::write (this->mmap_.handle (),
+ "",
+ 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ this->backing_store_name_),
+ -1);
+ }
+
+ // Increment by one to put us at the beginning of the next chunk...
+ map_size++;
+#endif /* CHORUS */
+ return 0;
+}
+
+// Memory map the file up to <map_size> bytes.
+
+int
+ACE_MMAP_Memory_Pool::map_file (off_t map_size)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file");
+
+ // Unmap the existing mapping.
+ this->mmap_.unmap ();
+
+ // Remap the file.
+ if (this->mmap_.map (map_size,
+ PROT_RDWR,
+ this->flags_,
+ this->base_addr_,
+ 0,
+ this->sa_) == -1
+ || this->base_addr_ != 0 && this->mmap_.addr () != this->base_addr_)
+ {
+#if 0
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) addr = %u, base_addr = %u, map_size = %u, %p\n"),
+ this->mmap_.addr (),
+ this->base_addr_,
+ map_size,
+ this->backing_store_name_));
+#endif /* 0 */
+ return -1;
+ }
+ else
+ {
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ this->base_addr_ = this->mmap_.addr ();
+ ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_,
+ map_size);
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+ return 0;
+ }
+}
+
+// Ask operating system for more shared memory, increasing the mapping
+// accordingly. Note that this routine assumes that the appropriate
+// locks are held when it is called.
+
+void *
+ACE_MMAP_Memory_Pool::acquire (size_t nbytes,
+ size_t &rounded_bytes)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire");
+ rounded_bytes = this->round_up (nbytes);
+
+ // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes =
+ // %d, rounded_bytes = %d\n", nbytes, rounded_bytes));
+
+ off_t map_size;
+
+ if (this->commit_backing_store_name (rounded_bytes,
+ map_size) == -1)
+ return 0;
+ else if (this->map_file (map_size) == -1)
+ return 0;
+
+ // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d,
+ // rounded_bytes = %d, map_size = %d\n", nbytes, rounded_bytes,
+ // map_size));
+
+ return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes));
+}
+
+// Ask system for initial chunk of shared memory.
+
+void *
+ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire");
+
+ first_time = 0;
+
+ if (nbytes < (size_t) this->minimum_bytes_)
+ nbytes = this->minimum_bytes_;
+
+ if (this->mmap_.open (this->backing_store_name_,
+ O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
+ ACE_DEFAULT_FILE_PERMS, this->sa_) != -1)
+ {
+ // First time in, so need to acquire memory.
+ first_time = 1;
+ return this->acquire (nbytes, rounded_bytes);
+ }
+ else if (errno == EEXIST)
+ {
+ errno = 0;
+ // Reopen file *without* using O_EXCL...
+ if (this->mmap_.map (this->backing_store_name_,
+#if defined (CHORUS)
+ nbytes,
+#else
+ -1,
+#endif /* CHORUS */
+ O_RDWR,
+ ACE_DEFAULT_FILE_PERMS,
+ PROT_RDWR,
+ this->flags_,
+ this->base_addr_,
+ 0,
+ this->sa_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("open")),
+ 0);
+
+ return this->mmap_.addr ();
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("open")),
+ 0);
+}
+
+#if defined (ACE_WIN32)
+int
+ACE_MMAP_Memory_Pool::seh_selector (void *ep)
+{
+ DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
+
+ if (ecode == EXCEPTION_ACCESS_VIOLATION)
+ {
+ void * fault_addr = (void *)
+ ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
+
+ if (this->remap (fault_addr) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* ACE_WIN32 */
+
+int
+ACE_MMAP_Memory_Pool::remap (void *addr)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::remap");
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Remapping with fault address at: %X\n"), addr));
+ off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ());
+ // ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
+
+ if (!(addr < (void *) ((char *) this->mmap_.addr () + current_map_size)
+ && addr >= this->mmap_.addr ()))
+ return -1;
+
+ // Extend the mapping to cover the size of the backing store.
+ return this->map_file (current_map_size);
+}
+
+ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options (const void *base_addr,
+ int use_fixed_addr,
+ int write_each_page,
+ off_t minimum_bytes,
+ u_int flags,
+ int guess_on_fault,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (base_addr),
+ use_fixed_addr_ (base_addr == 0 ? 0 : use_fixed_addr),
+ write_each_page_ (write_each_page),
+ minimum_bytes_ (minimum_bytes),
+ flags_ (flags),
+ guess_on_fault_ (guess_on_fault),
+ sa_ (sa)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options");
+ // HP-UX 11, 64-bit bug workaround.
+#if defined (__hpux) && defined (__LP64__)
+ long temp = ACE_DEFAULT_BASE_ADDRL;
+ base_addr_ = (void *) temp;
+#endif /* defined (__hpux) && defined (__LP64__) */
+}
+
+// Handle SIGSEGV and SIGBUS signals to remap memory properly. When a
+// process reads or writes to non-mapped memory a signal (SIGBUS or
+// SIGSEGV) will be triggered. At that point, the ACE_Sig_Handler
+// (which is part of the ACE_Reactor) will catch the signal and
+// dispatch the handle_signal() method defined here. If the SIGSEGV
+// signal occurred due to the fact that the mapping wasn't uptodate
+// with respect to the backing store, the handler method below will
+// update the mapping accordingly. When the signal handler returns,
+// the instruction should be restarted and the operation should work.
+
+int
+ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *)
+{
+ if (signum != SIGSEGV)
+ return -1;
+ else
+ ; // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) received %S\n"), signum));
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) new mapping address = %u\n"), (char *) this->base_addr_ + current_map_size));
+
+#if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
+ // Make sure that the pointer causing the problem is within the
+ // range of the backing store.
+
+ if (siginfo != 0)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr));
+ if (this->remap ((void *) siginfo->si_addr) == -1)
+ return -1;
+ // ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n",
+ // siginfo->si_addr), -1);
+ return 0;
+ }
+#else
+ ACE_UNUSED_ARG(siginfo);
+#endif /* ACE_HAS_SIGINFO_T && !defined ACE_LACKS_SI_ADDR */
+ // If guess_on_fault_ is true, then we want to try to remap without
+ // knowing the faulting address. guess_on_fault_ can only be true
+ // on platforms that do not provide the faulting address through
+ // signals or exceptions. We check to see if the mapping is up to
+ // date. If it is, then this fault isn't due to this mapping and we
+ // pass it on.
+ if (guess_on_fault_)
+ {
+ // Check if the current mapping is up to date.
+ off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ());
+
+ if (ACE_static_cast (size_t, current_map_size) == this->mmap_.size ())
+ {
+ // The mapping is up to date so this really is a bad
+ // address. Thus, remove current signal handler so process
+ // will fail with default action and core file will be
+ // written.
+ this->signal_handler_.remove_handler (SIGSEGV);
+ return 0;
+ }
+
+ // Extend the mapping to cover the size of the backing store.
+ return this->map_file (current_map_size);
+ }
+ else
+ return -1;
+}
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool)
+
+ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
+ const OPTIONS *options)
+ : ACE_MMAP_Memory_Pool (backing_store_name, options)
+{
+ ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool");
+}
+
+int
+ACE_Lite_MMAP_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
+ return 0;
+}
+
+int
+ACE_Lite_MMAP_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
+ return 0;
+}
+
+#if !defined (ACE_LACKS_SBRK)
+ACE_ALLOC_HOOK_DEFINE(ACE_Sbrk_Memory_Pool)
+
+// Ask system for more local memory via sbrk(2).
+
+void *
+ACE_Sbrk_Memory_Pool::acquire (size_t nbytes,
+ size_t &rounded_bytes)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::acquire");
+ rounded_bytes = this->round_up (nbytes);
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
+ void *cp = ACE_OS::sbrk (rounded_bytes);
+
+ if (cp == MAP_FAILED)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) cp = %u\n",
+ cp),
+ 0);
+ else
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n"), nbytes, rounded_bytes, cp));
+ return cp;
+}
+
+void
+ACE_Sbrk_Memory_Pool::dump (void) const
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump");
+}
+
+ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const ACE_TCHAR *,
+ const OPTIONS *)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool");
+}
+#endif /* !ACE_LACKS_SBRK */
+
+#if !defined (ACE_LACKS_SYSV_SHMEM)
+ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool)
+
+ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options (const char *base_addr,
+ size_t max_segments,
+ size_t file_perms,
+ off_t minimum_bytes,
+ size_t segment_size)
+ : base_addr_ (base_addr),
+ max_segments_ (max_segments),
+ minimum_bytes_ (minimum_bytes),
+ file_perms_ (file_perms),
+ segment_size_ (segment_size)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options");
+ // HP-UX 11, 64-bit bug workaround
+#if defined (__hpux) && defined (__LP64__)
+ long temp = ACE_DEFAULT_BASE_ADDRL;
+ base_addr_ = (char *) temp;
+#endif /* defined (__hpux) && defined (__LP64__) */
+}
+
+void
+ACE_Shared_Memory_Pool::dump (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::dump");
+}
+
+int
+ACE_Shared_Memory_Pool::in_use (off_t &offset,
+ size_t &counter)
+{
+ offset = 0;
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+ shmid_ds buf;
+
+ for (counter = 0;
+ counter < this->max_segments_ && st[counter].used_ == 1;
+ counter++)
+ {
+ if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("shmctl")),
+ -1);
+ offset += buf.shm_segsz;
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset));
+ }
+
+ return 0;
+}
+
+int
+ACE_Shared_Memory_Pool::find_seg (const void* const searchPtr,
+ off_t &offset,
+ size_t &counter)
+{
+ offset = 0;
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+ shmid_ds buf;
+
+ for (counter = 0;
+ counter < this->max_segments_
+ && st[counter].used_ == 1;
+ counter++)
+ {
+ if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("shmctl")),
+ -1);
+ offset += buf.shm_segsz;
+
+ // If segment 'counter' starts at a location greater than the
+ // place we are searching for. We then decrement the offset to
+ // the start of counter-1. (flabar@vais.net)
+ if ((offset + (off_t)(this->base_addr_) ) > (off_t)searchPtr)
+ {
+ --counter;
+ offset -= buf.shm_segsz;
+ return 0;
+ }
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset));
+ }
+
+ return 0;
+}
+
+int
+ACE_Shared_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
+ off_t &offset)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::commit_backing_store_name");
+
+ size_t counter;
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+
+ if (this->in_use (offset, counter) == -1)
+ return -1;
+
+ if (counter == this->max_segments_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "exceeded max number of segments = %d, base = %u, offset = %u\n",
+ counter,
+ this->base_addr_,
+ offset),
+ -1);
+ else
+ {
+ int shmid = ACE_OS::shmget (st[counter].key_,
+ rounded_bytes,
+ this->file_perms_ | IPC_CREAT | IPC_EXCL);
+ if (shmid == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("shmget")),
+ 0);
+ st[counter].shmid_ = shmid;
+ st[counter].used_ = 1;
+
+ void *address = (void *) (((char *) this->base_addr_) + offset);
+ void *shmem = ACE_OS::shmat (st[counter].shmid_,
+ (char *) address,
+ 0);
+
+ if (shmem != address)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p, shmem = %u, address = %u\n",
+ "shmat",
+ shmem,
+ address),
+ 0);
+ }
+ return 0;
+}
+
+// Handle SIGSEGV and SIGBUS signals to remap shared memory properly.
+
+int
+ACE_Shared_Memory_Pool::handle_signal (int , siginfo_t *siginfo, ucontext_t *)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal");
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("signal %S occurred\n"), signum));
+
+#if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
+ off_t offset;
+ // Make sure that the pointer causing the problem is within the
+ // range of the backing store.
+
+ if (siginfo != 0)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr));
+ size_t counter;
+ if (this->in_use (offset, counter) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("in_use")));
+#if !defined(_UNICOS)
+ else if (!(siginfo->si_code == SEGV_MAPERR
+ && siginfo->si_addr < (((char *) this->base_addr_) + offset)
+ && siginfo->si_addr >= ((char *) this->base_addr_)))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) address %u out of range\n",
+ siginfo->si_addr),
+ -1);
+#else /* ! _UNICOS */
+ else if (!(siginfo->si_code == SEGV_MEMERR
+ && siginfo->si_addr < (((unsigned long) this->base_addr_) + offset)
+ && siginfo->si_addr >= ((unsigned long) this->base_addr_)))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) address %u out of range\n",
+ siginfo->si_addr),
+ -1);
+#endif /* ! _UNICOS */
+ }
+
+ // The above if case will check to see that the address is in the
+ // proper range. Therefore there is a segment out there that the
+ // pointer wants to point into. Find the segment that someone else
+ // has used and attach to it (flabar@vais.net)
+
+ size_t counter; // ret value to get shmid from the st table.
+
+#if !defined(_UNICOS)
+ if (this->find_seg (siginfo->si_addr, offset, counter) == -1)
+#else /* ! _UNICOS */
+ if (this->find_seg ((const void *)siginfo->si_addr, offset, counter) == -1)
+#endif /* ! _UNICOS */
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("in_use")),
+ -1);
+
+ void *address = (void *) (((char *) this->base_addr_) + offset);
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+
+ void *shmem = ACE_OS::shmat (st[counter].shmid_, (char *) address, 0);
+
+ if (shmem != address)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p, shmem = %u, address = %u\n",
+ "shmat",
+ shmem,
+ address),
+ 0);
+
+ // NOTE: this won't work if we dont have SIGINFO_T or SI_ADDR
+#else
+ ACE_UNUSED_ARG (siginfo);
+#endif /* ACE_HAS_SIGINFO_T && !defined (ACE_LACKS_SI_ADDR) */
+
+ return 0;
+}
+
+ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name,
+ const OPTIONS *options)
+ : base_addr_ (0),
+ file_perms_ (ACE_DEFAULT_FILE_PERMS),
+ max_segments_ (ACE_DEFAULT_MAX_SEGMENTS),
+ minimum_bytes_ (0),
+ segment_size_ (ACE_DEFAULT_SEGMENT_SIZE)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool");
+
+ // Only change the defaults if <options> != 0.
+ if (options)
+ {
+ this->base_addr_ =
+ ACE_reinterpret_cast (void *,
+ ACE_const_cast (char *,
+ options->base_addr_));
+ this->max_segments_ = options->max_segments_;
+ this->file_perms_ = options->file_perms_;
+ this->minimum_bytes_ = options->minimum_bytes_;
+ this->segment_size_ = options->segment_size_;
+ }
+
+ if (backing_store_name)
+ {
+ // Convert the string into a number that is used as the segment
+ // key.
+
+ int segment_key;
+ int result = ::sscanf (backing_store_name,
+ "%d",
+ &segment_key);
+
+ if (result == 0 || result == EOF)
+ // The conversion to a number failed so hash with crc32
+ // ACE::crc32 is also used in <SV_Semaphore_Simple>.
+ this->base_shm_key_ = (key_t) ACE::crc32 (backing_store_name);
+ else
+ this->base_shm_key_ = segment_key;
+
+ if (this->base_shm_key_ == IPC_PRIVATE)
+ // Make sure that the segment can be shared between unrelated
+ // processes.
+ this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
+ }
+ else
+ this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
+
+ if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Sig_Handler::register_handler")));
+}
+
+// Ask system for more shared memory.
+
+void *
+ACE_Shared_Memory_Pool::acquire (size_t nbytes,
+ size_t &rounded_bytes)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::acquire");
+
+ rounded_bytes = this->round_up (nbytes);
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
+
+ off_t offset;
+
+ if (this->commit_backing_store_name (rounded_bytes, offset) == -1)
+ return 0;
+
+ // ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
+ return ((char *) this->base_addr_) + offset;
+}
+
+// Ask system for initial chunk of shared memory.
+
+void *
+ACE_Shared_Memory_Pool::init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire");
+
+ off_t shm_table_offset = ACE::round_to_pagesize (sizeof (SHM_TABLE));
+ rounded_bytes = this->round_up (nbytes > (size_t) this->minimum_bytes_
+ ? nbytes
+ : (size_t) this->minimum_bytes_);
+
+ // Acquire the semaphore to serialize initialization and prevent
+ // race conditions.
+
+ int shmid = ACE_OS::shmget (this->base_shm_key_,
+ rounded_bytes + shm_table_offset,
+ this->file_perms_ | IPC_CREAT | IPC_EXCL);
+ if (shmid == -1)
+ {
+ if (errno != EEXIST)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("shmget")),
+ 0);
+ first_time = 0;
+
+ shmid = ACE_OS::shmget (this->base_shm_key_, 0, 0);
+
+ if (shmid == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) %p\n"),
+ ACE_LIB_TEXT ("shmget")),
+ 0);
+
+ // This implementation doesn't care if we don't get the key we
+ // want...
+ this->base_addr_ =
+ ACE_OS::shmat (shmid,
+ ACE_reinterpret_cast (char *,
+ this->base_addr_),
+ 0);
+ if (this->base_addr_ == ACE_reinterpret_cast (void *, -1))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p, base_addr = %u\n",
+ "shmat",
+ this->base_addr_),
+ 0);
+ }
+ else
+ {
+ first_time = 1;
+
+ // This implementation doesn't care if we don't get the key we
+ // want...
+ this->base_addr_ =
+ ACE_OS::shmat (shmid,
+ ACE_reinterpret_cast (char *,
+ this->base_addr_),
+ 0);
+ if (this->base_addr_ == ACE_reinterpret_cast (char *, -1))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p, base_addr = %u\n",
+ "shmat",
+ this->base_addr_), 0);
+
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+ st[0].key_ = this->base_shm_key_;
+ st[0].shmid_ = shmid;
+
+ st[0].used_ = 1;
+
+ for (size_t counter = 1; // Skip over the first entry...
+ counter < this->max_segments_;
+ counter++)
+ {
+ st[counter].key_ = this->base_shm_key_ + counter;
+ st[counter].shmid_ = 0;
+ st[counter].used_ = 0;
+ }
+ }
+
+ return (void *) (((char *) this->base_addr_) + shm_table_offset);
+}
+
+// Instruct the memory pool to release all of its resources.
+
+int
+ACE_Shared_Memory_Pool::release (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::release");
+
+ int result = 0;
+ SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
+ this->base_addr_);
+
+ for (size_t counter = 0;
+ counter < this->max_segments_ && st[counter].used_ == 1;
+ counter++)
+ if (ACE_OS::shmctl (st[counter].shmid_, IPC_RMID, 0) == -1)
+ result = -1;
+
+ return result;
+}
+#endif /* !ACE_LACKS_SYSV_SHMEM */
+
+#if defined (ACE_WIN32)
+#if !defined (ACE_HAS_WINCE)
+#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
+ MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
+#else //if !defined (ACE_HAS_WINCE)
+#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
+ MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
+#endif /* !defined (ACE_HAS_WINCE) */
+
+ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (void *base_addr,
+ size_t max_size)
+ : base_addr_ (base_addr),
+ max_size_ (max_size)
+{
+}
+
+int
+ACE_Pagefile_Memory_Pool::release (void)
+{
+ return this->unmap ();
+}
+
+ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
+ const OPTIONS *options)
+ : shared_cb_ (0),
+ object_handle_ (0),
+ page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
+{
+ // Initialize local copy of pool statistics.
+ if (options != 0)
+ {
+ this->local_cb_.req_base_ = options->base_addr_;
+ this->local_cb_.mapped_base_ = 0;
+ this->local_cb_.sh_.max_size_ =
+ options->max_size_;
+ this->local_cb_.sh_.mapped_size_ = 0;
+ this->local_cb_.sh_.free_offset_ =
+ this->local_cb_.sh_.mapped_size_;
+ this->local_cb_.sh_.free_size_ = 0;
+ }
+
+ if (backing_store_name == 0)
+ // Only create a new unique filename for the backing store file if
+ // the user didn't supply one...
+ backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
+
+ ACE_OS::strsncpy (this->backing_store_name_,
+ backing_store_name,
+ (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
+}
+
+void *
+ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
+ size_t &rounded_bytes)
+{
+ rounded_bytes = round_to_page_size (nbytes);
+ void *result = 0;
+ int first_time = 0;
+
+ // Check local_cb_ for consistency. Remap, if extra space is too
+ // small and/or we didn't map the whole shared memory section
+ if (this->shared_cb_->sh_.mapped_size_
+ > this->local_cb_.sh_.mapped_size_
+ || this->shared_cb_->sh_.free_size_
+ < (int) rounded_bytes)
+ {
+ int append =
+ rounded_bytes - this->shared_cb_->sh_.free_size_;
+ if (append < 0)
+ append = 0;
+
+ if (this->map (first_time, append) < 0)
+ return result;
+ }
+
+ // Get the block from extra space and update shared and local
+ // control block
+ if (this->shared_cb_->sh_.free_size_
+ < (int) rounded_bytes)
+ return result;
+
+ result = (void *)((char *) this->local_cb_.mapped_base_
+ + this->shared_cb_->sh_.free_offset_);
+ this->shared_cb_->sh_.free_offset_ += rounded_bytes;
+ this->shared_cb_->sh_.free_size_ -= rounded_bytes;
+ this->local_cb_.sh_ = this->shared_cb_->sh_;
+
+ return result;
+}
+
+void *
+ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time)
+{
+ // Map the shared memory and get information, if we created the
+ // shared memory.
+ if (this->map (first_time) < 0)
+ return 0;
+
+ if (first_time != 0)
+ // We created the shared memory. So we have to allocate the
+ // requested memory.
+ return this->acquire (nbytes, rounded_bytes);
+ else
+ // We just mapped the memory and return the base address
+ return (void *)((char *) this->local_cb_.mapped_base_
+ + ACE_Pagefile_Memory_Pool::round_to_page_size
+ ((int) sizeof (Control_Block)));
+}
+
+int
+ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
+{
+ DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
+
+ if (ecode == EXCEPTION_ACCESS_VIOLATION)
+ {
+ void * fault_addr = (void *)
+ ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
+
+ if (this->remap (fault_addr) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+ACE_Pagefile_Memory_Pool::remap (void *addr)
+{
+ // If the shared memory is not mapped or the address, that caused
+ // the memory fault is outside of the commited range of chunks, we
+ // return.
+ if (this->shared_cb_ == 0
+ || addr < this->local_cb_.mapped_base_
+ || addr >= (void *)((char *) this->local_cb_.mapped_base_
+ + this->shared_cb_->sh_.mapped_size_))
+ return -1;
+
+ // We can solve the problem by committing additional chunks.
+ int first_time = 0;
+ return this->map (first_time);
+}
+
+int
+ACE_Pagefile_Memory_Pool::unmap (void)
+{
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
+ (this->local_cb_.mapped_base_);
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ // Cleanup cached pool pointer.
+ this->shared_cb_ = 0;
+
+ if (this->local_cb_.sh_.mapped_size_ > 0)
+ ::UnmapViewOfFile (this->local_cb_.mapped_base_);
+
+ // Reset local pool statistics.
+ this->local_cb_.req_base_ =
+ ACE_DEFAULT_PAGEFILE_POOL_BASE;
+ this->local_cb_.mapped_base_ = 0;
+ this->local_cb_.sh_.max_size_ =
+ ACE_DEFAULT_PAGEFILE_POOL_SIZE;
+ this->local_cb_.sh_.mapped_size_ = 0;
+ this->local_cb_.sh_.free_offset_ =
+ this->local_cb_.sh_.mapped_size_;
+ this->local_cb_.sh_.free_size_ = 0;
+
+ // Release the pool
+ if (this->object_handle_ != 0)
+ {
+ ::CloseHandle (this->object_handle_);
+ this->object_handle_ = 0;
+ }
+ return 0;
+}
+
+int
+ACE_Pagefile_Memory_Pool::map (int &first_time,
+ int append_bytes)
+{
+ int map_size;
+ void *map_addr;
+
+ // Create file mapping, if not yet done
+ if (object_handle_ == 0)
+ {
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ // Allow access by all users.
+ SECURITY_ATTRIBUTES sa;
+ SECURITY_DESCRIPTOR sd;
+ ::InitializeSecurityDescriptor (&sd,
+ SECURITY_DESCRIPTOR_REVISION);
+ ::SetSecurityDescriptorDacl (&sd,
+ TRUE,
+ NULL,
+ FALSE);
+ sa.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = FALSE;
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
+
+ // Get an object handle to the named reserved memory object.
+ object_handle_ =
+ ACE_TEXT_CreateFileMapping ((HANDLE) 0xffffffff,
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ &sa,
+#else
+ NULL,
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
+ PAGE_READWRITE | SEC_RESERVE,
+ 0,
+ this->local_cb_.sh_.max_size_,
+ this->backing_store_name_);
+ if (object_handle_ == 0)
+ return -1;
+ first_time =
+ ::GetLastError () == ERROR_ALREADY_EXISTS
+ ? 0
+ : 1;
+ }
+
+ // Do the initial mapping.
+ if (this->shared_cb_ == 0)
+ {
+ // Map a view to the shared memory. Note: <MapViewOfFile[Ex]>
+ // does *not* commit the pages!
+ this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
+ ACE_MAP_FILE (this->object_handle_,
+ FILE_MAP_WRITE,
+ 0,
+ 0,
+ this->local_cb_.sh_.max_size_,
+ this->local_cb_.req_base_);
+ if (this->shared_cb_ == 0)
+ return -1;
+
+ // There was no previous mapping, so we map the first chunk and
+ // initialize the shared pool statistics.
+ if (first_time)
+ {
+ // 1st block is used to keep shared memory statistics.
+ map_size =
+ ACE_Pagefile_Memory_Pool::round_to_chunk_size
+ (ACE_Pagefile_Memory_Pool::round_to_page_size
+ ((int) sizeof(Control_Block))
+ + append_bytes);
+
+ if (::VirtualAlloc ((void *) this->shared_cb_,
+ map_size,
+ MEM_COMMIT,
+ PAGE_READWRITE) == 0)
+ return -1;
+
+ this->shared_cb_->req_base_ = 0;
+ this->shared_cb_->mapped_base_ = 0;
+ this->local_cb_.mapped_base_ = this->shared_cb_;
+ this->local_cb_.sh_.mapped_size_ = map_size;
+ this->local_cb_.sh_.free_offset_ =
+ round_to_page_size ((int) sizeof (Control_Block));
+ this->local_cb_.sh_.free_size_ =
+ this->local_cb_.sh_.mapped_size_ -
+ this->local_cb_.sh_.free_offset_;
+ this->shared_cb_->sh_ = this->local_cb_.sh_;
+ }
+
+ // The shared memory exists, so we map the first chunk to the
+ // base address of the pool to get the shared pool statistics.
+ else
+ {
+ // 1st block is used to keep shared memory statistics.
+ map_size =
+ ACE_Pagefile_Memory_Pool::round_to_chunk_size
+ ((int) sizeof (Control_Block));
+
+ if (::VirtualAlloc ((void *) this->shared_cb_,
+ map_size,
+ MEM_COMMIT,
+ PAGE_READWRITE) == 0)
+ return -1;
+ this->local_cb_.mapped_base_ = this->shared_cb_;
+ this->local_cb_.sh_.mapped_size_ = map_size;
+ }
+ }
+
+ // If the shared memory is larger than the part we've already
+ // committed, we have to remap it.
+ if (this->shared_cb_->sh_.mapped_size_ >
+ this->local_cb_.sh_.mapped_size_
+ || append_bytes > 0)
+ {
+ map_size =
+ (this->shared_cb_->sh_.mapped_size_ -
+ this->local_cb_.sh_.mapped_size_)
+ + ACE_Pagefile_Memory_Pool::round_to_chunk_size
+ (append_bytes);
+
+ map_addr = (void *)((char *) this->shared_cb_ +
+ this->local_cb_.sh_.mapped_size_);
+
+ if (::VirtualAlloc (map_addr,
+ map_size,
+ MEM_COMMIT,
+ PAGE_READWRITE) == 0)
+ return -1;
+ else if (append_bytes > 0)
+ {
+ this->shared_cb_->sh_.mapped_size_ +=
+ round_to_chunk_size (append_bytes);
+ this->shared_cb_->sh_.free_size_ =
+ this->shared_cb_->sh_.mapped_size_ -
+ this->shared_cb_->sh_.free_offset_;
+ }
+ }
+
+ // Update local copy of the shared memory statistics.
+ this->local_cb_.sh_ =
+ this->shared_cb_->sh_;
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ ACE_BASED_POINTER_REPOSITORY::instance ()->bind
+ (this->local_cb_.mapped_base_,
+ this->local_cb_.sh_.mapped_size_);
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+ return 0;
+}
+
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Auto_Basic_Array_Ptr<char>;
+template class ACE_Unbounded_Set<char *>;
+template class ACE_Unbounded_Set_Iterator<char *>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Auto_Basic_Array_Ptr<char>
+#pragma instantiate ACE_Unbounded_Set<char *>
+#pragma instantiate ACE_Unbounded_Set_Iterator<char *>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Memory/Memory_Pool.h b/ace/Memory/Memory_Pool.h
new file mode 100644
index 00000000000..896887bc886
--- /dev/null
+++ b/ace/Memory/Memory_Pool.h
@@ -0,0 +1,756 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Memory_Pool.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and Prashant Jain <pjain@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MEMORY_POOL_H
+#define ACE_MEMORY_POOL_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+#include "ace/Signal.h"
+#include "ace/Mem_Map.h"
+#if !defined (ACE_WIN32)
+#include "ace/SV_Semaphore_Complex.h"
+#endif /* !ACE_WIN32 */
+
+#include "ace/Unbounded_Set.h"
+
+#if !defined (ACE_LACKS_SBRK)
+/**
+ * @class ACE_Sbrk_Memory_Pool_Options
+ *
+ * @brief Helper class for Sbrk Memory Pool constructor options.
+ *
+ * This should be a nested class, but that breaks too many
+ * compilers.
+ */
+class ACE_Export ACE_Sbrk_Memory_Pool_Options
+{
+};
+
+/**
+ * @class ACE_Sbrk_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on <sbrk(2)>.
+ */
+class ACE_Export ACE_Sbrk_Memory_Pool
+{
+public:
+ typedef ACE_Sbrk_Memory_Pool_Options OPTIONS;
+
+ /// Initialize the pool.
+ ACE_Sbrk_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ virtual ~ACE_Sbrk_Memory_Pool (void);
+
+ // = Implementor operations.
+ /// Ask system for initial chunk of local memory.
+ virtual void *init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time);
+
+ /// Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is
+ /// the actual number of bytes allocated.
+ virtual void *acquire (size_t nbytes,
+ size_t &rounded_bytes);
+
+ /// Instruct the memory pool to release all of its resources.
+ virtual int release (void);
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If <len> == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Implement the algorithm for rounding up the request to an
+ /// appropriate chunksize.
+ virtual size_t round_up (size_t nbytes);
+};
+#endif /* !ACE_LACKS_SBRK */
+
+#if !defined (ACE_LACKS_SYSV_SHMEM)
+
+/**
+ * @class ACE_Shared_Memory_Pool_Options
+ *
+ * @brief Helper class for Shared Memory Pool constructor options.
+ *
+ * This should be a nested class, but that breaks too many
+ * compilers.
+ */
+class ACE_Export ACE_Shared_Memory_Pool_Options
+{
+public:
+ // = Initialization method.
+ ACE_Shared_Memory_Pool_Options (const char *base_addr = ACE_DEFAULT_BASE_ADDR,
+ size_t max_segments = ACE_DEFAULT_MAX_SEGMENTS,
+ size_t file_perms = ACE_DEFAULT_FILE_PERMS,
+ off_t minimum_bytes = 0,
+ size_t segment_size = ACE_DEFAULT_SEGMENT_SIZE);
+
+ /// Base address of the memory-mapped backing store.
+ const char *base_addr_;
+
+ /// Number of shared memory segments to allocate.
+ size_t max_segments_;
+
+ /// What the minimum bytes of the initial segment should be.
+ off_t minimum_bytes_;
+
+ /// File permissions to use when creating/opening a segment.
+ size_t file_perms_;
+
+ /// Shared memory segment size.
+ size_t segment_size_;
+};
+
+/**
+ * @class ACE_Shared_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on System V shared memory
+ * (shmget(2) etc.). This implementation allows memory to be
+ * shared between processes. If your platform doesn't support
+ * System V shared memory (e.g., Win32 and many RTOS platforms
+ * do not) then you should use ACE_MMAP_Memory_Pool instead of this
+ * class. In fact, you should probably use ACE_MMAP_Memory_Pool on
+ * platforms that *do* support System V shared memory since it
+ * provides more powerful features, such as persistent backing store
+ * and greatly scalability.
+ */
+class ACE_Export ACE_Shared_Memory_Pool : public ACE_Event_Handler
+{
+public:
+ typedef ACE_Shared_Memory_Pool_Options OPTIONS;
+
+ /// Initialize the pool.
+ ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ virtual ~ACE_Shared_Memory_Pool (void);
+
+ /// Ask system for initial chunk of local memory.
+ virtual void *init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time);
+
+ /**
+ * Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is
+ * the actual number of bytes allocated. Also acquires an internal
+ * semaphore that ensures proper serialization of Memory_Pool
+ * initialization across processes.
+ */
+ virtual void *acquire (size_t nbytes,
+ size_t &rounded_bytes);
+
+ /// Instruct the memory pool to release all of its resources.
+ virtual int release (void);
+
+ /// Sync the memory region to the backing store starting at
+ /// <this->base_addr_>.
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync the memory region to the backing store starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Implement the algorithm for rounding up the request to an
+ /// appropriate chunksize.
+ virtual size_t round_up (size_t nbytes);
+
+ /**
+ * Commits a new shared memory segment if necessary after an
+ * <acquire> or a signal. <offset> is set to the new offset into
+ * the backing store.
+ */
+ virtual int commit_backing_store_name (size_t rounded_bytes,
+ off_t &offset);
+
+ // = Keeps track of all the segments being used.
+ struct SHM_TABLE
+ {
+ key_t key_;
+ // Shared memory segment key.
+
+ int shmid_;
+ // Shared memory segment internal id.
+
+ int used_;
+ // Is the segment currently used.;
+ };
+
+ /**
+ * Base address of the shared memory segment. If this has the value
+ * of 0 then the OS is free to select any address, otherwise this
+ * value is what the OS must try to use to map the shared memory
+ * segment.
+ */
+ void *base_addr_;
+
+ /// File permissions to use when creating/opening a segment.
+ size_t file_perms_;
+
+ /// Number of shared memory segments in the <SHM_TABLE> table.
+ size_t max_segments_;
+
+ /// What the minimim bytes of the initial segment should be.
+ off_t minimum_bytes_;
+
+ /// Shared memory segment size.
+ size_t segment_size_;
+
+ /// Base shared memory key for the segment.
+ key_t base_shm_key_;
+
+ /// find the segment that contains the searchPtr
+ virtual int find_seg (const void *const searchPtr,
+ off_t &offset,
+ size_t &counter);
+
+ /// Determine how much memory is currently in use.
+ virtual int in_use (off_t &offset,
+ size_t &counter);
+
+ /// Handles SIGSEGV.
+ ACE_Sig_Handler signal_handler_;
+
+ /// Handle SIGSEGV and SIGBUS signals to remap shared memory
+ /// properly.
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+};
+#endif /* !ACE_LACKS_SYSV_SHMEM */
+
+/**
+ * @class ACE_Local_Memory_Pool_Options
+ *
+ * @brief Helper class for Local Memory Pool constructor options.
+ *
+ * This should be a nested class, but that breaks too many
+ * compilers.
+ */
+class ACE_Export ACE_Local_Memory_Pool_Options
+{
+};
+
+/**
+ * @class ACE_Local_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on C++ new/delete. This is
+ * useful for integrating existing components that use new/delete
+ * into the ACE Malloc scheme...
+ */
+class ACE_Export ACE_Local_Memory_Pool
+{
+public:
+ typedef ACE_Local_Memory_Pool_Options OPTIONS;
+
+ /// Initialize the pool.
+ ACE_Local_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ virtual ~ACE_Local_Memory_Pool (void);
+
+ /// Ask system for initial chunk of local memory.
+ virtual void *init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time);
+
+ /// Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is
+ /// the actual number of bytes allocated.
+ virtual void *acquire (size_t nbytes,
+ size_t &rounded_bytes);
+
+ /// Instruct the memory pool to release all of its resources.
+ virtual int release (void);
+
+ /**
+ * Sync <len> bytes of the memory region to the backing store
+ * starting at <this->base_addr_>. If <len> == -1 then sync the
+ * whole region.
+ */
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync <len> bytes of the memory region to the backing store
+ /// starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+#if defined (ACE_WIN32)
+ /**
+ * Win32 Structural exception selector. The return value decides
+ * how to handle memory pool related structural exceptions. Returns
+ * 1, 0, or , -1.
+ */
+ virtual int seh_selector (void *);
+#endif /* ACE_WIN32 */
+
+ /**
+ * Try to extend the virtual address space so that <addr> is now
+ * covered by the address mapping. Always returns 0 since we can't
+ * remap a local memory pool.
+ */
+ virtual int remap (void *addr);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// List of memory that we have allocated.
+ ACE_Unbounded_Set<char *> allocated_chunks_;
+
+ virtual size_t round_up (size_t nbytes);
+
+ // Implement the algorithm for rounding up the request to an
+ // appropriate chunksize.
+};
+
+/**
+ * @class ACE_MMAP_Memory_Pool_Options
+ *
+ * @brief Helper class for MMAP Memory Pool constructor options.
+ *
+ * This should be a nested class, but that breaks too many
+ * compilers.
+ */
+class ACE_Export ACE_MMAP_Memory_Pool_Options
+{
+public:
+ // = Initialization method.
+ ACE_MMAP_Memory_Pool_Options (const void *base_addr = ACE_DEFAULT_BASE_ADDR,
+ int use_fixed_addr = 1,
+ int write_each_page = 1,
+ off_t minimum_bytes = 0,
+ u_int flags = 0,
+ int guess_on_fault = 1,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ /// Base address of the memory-mapped backing store.
+ const void *base_addr_;
+
+ /// Must we use the <base_addr_> or can we let mmap(2) select it?
+ int use_fixed_addr_;
+
+ /// Should each page be written eagerly to avoid surprises later
+ /// on?
+ int write_each_page_;
+
+ /// What the minimim bytes of the initial segment should be.
+ off_t minimum_bytes_;
+
+ /// Any special flags that need to be used for <mmap>.
+ u_int flags_;
+
+ /**
+ * Try to remap without knowing the faulting address. This
+ * parameter is ignored on platforms that know the faulting address
+ * (UNIX with SI_ADDR and Win32).
+ */
+ int guess_on_fault_;
+
+ /// Pointer to a security attributes object. Only used on NT.
+ LPSECURITY_ATTRIBUTES sa_;
+
+};
+
+/**
+ * @class ACE_MMAP_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on <mmap(2)>. This
+ * implementation allows memory to be shared between processes.
+ */
+class ACE_Export ACE_MMAP_Memory_Pool : public ACE_Event_Handler
+{
+public:
+ typedef ACE_MMAP_Memory_Pool_Options OPTIONS;
+
+ // = Initialization and termination methods.
+
+ /// Initialize the pool.
+ ACE_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ virtual ~ACE_MMAP_Memory_Pool (void);
+
+ /// Ask system for initial chunk of shared memory.
+ virtual void *init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time);
+
+ /**
+ * Acquire at least <nbytes> from the memory pool. <rounded_bytes>
+ * is the actual number of bytes allocated. Also acquires an
+ * internal semaphore that ensures proper serialization of
+ * <ACE_MMAP_Memory_Pool> initialization across processes.
+ */
+ virtual void *acquire (size_t nbytes,
+ size_t &rounded_bytes);
+
+ /// Instruct the memory pool to release all of its resources.
+ virtual int release (void);
+
+ /// Sync the memory region to the backing store starting at
+ /// <this->base_addr_>.
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Sync the memory region to the backing store starting at <addr_>.
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+
+ /**
+ * Change the protection of the pages of the mapped region to <prot>
+ * starting at <this->base_addr_> up to <len> bytes. If <len> == -1
+ * then change protection of all pages in the mapped region.
+ */
+ virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
+
+ /// Change the protection of the pages of the mapped region to <prot>
+ /// starting at <addr> up to <len> bytes.
+ virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
+
+#if defined (ACE_WIN32)
+ /**
+ * Win32 Structural exception selector. The return value decides
+ * how to handle memory pool related structural exceptions. Returns
+ * 1, 0, or , -1.
+ */
+ virtual int seh_selector (void *);
+#endif /* ACE_WIN32 */
+
+ /**
+ * Try to extend the virtual address space so that <addr> is now
+ * covered by the address mapping. The method succeeds and returns
+ * 0 if the backing store has adequate memory to cover this address.
+ * Otherwise, it returns -1. This method is typically called by a
+ * UNIX signal handler for SIGSEGV or a Win32 structured exception
+ * when another process has grown the backing store (and its
+ * mapping) and our process now incurs a fault because our mapping
+ * isn't in range (yet).
+ */
+ virtual int remap (void *addr);
+
+
+ /// Return the base address of this memory pool.
+ virtual void *base_addr (void) const;
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Implement the algorithm for rounding up the request to an
+ // appropriate chunksize.
+
+ virtual size_t round_up (size_t nbytes);
+
+ /// Compute the new <map_size> of the backing store and commit the
+ /// memory.
+ virtual int commit_backing_store_name (size_t rounded_bytes,
+ off_t &map_size);
+
+ /// Memory map the file up to <map_size> bytes.
+ virtual int map_file (off_t map_size);
+
+ /// Handle SIGSEGV and SIGBUS signals to remap shared memory
+ /// properly.
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+
+ /// Handles SIGSEGV.
+ ACE_Sig_Handler signal_handler_;
+
+ /// Memory-mapping object.
+ ACE_Mem_Map mmap_;
+
+ /**
+ * Base of mapped region. If this has the value of 0 then the OS is
+ * free to select any address to map the file, otherwise this value
+ * is what the OS must try to use to mmap the file.
+ */
+ void *base_addr_;
+
+ /// Flags passed into <ACE_OS::mmap>.
+ int flags_;
+
+ /// Should we write a byte to each page to forceably allocate memory
+ /// for this backing store?
+ int write_each_page_;
+
+ /// What the minimum bytes of the initial segment should be.
+ off_t minimum_bytes_;
+
+ /// Name of the backing store where the shared memory pool is kept.
+ ACE_TCHAR backing_store_name_[MAXPATHLEN + 1];
+
+ /**
+ * Try to remap without knowing the faulting address. This
+ * parameter is ignored on platforms that know the faulting address
+ * (UNIX with SI_ADDR and Win32).
+ */
+ int guess_on_fault_;
+
+ /// Security attributes object, only used on NT.
+ LPSECURITY_ATTRIBUTES sa_;
+
+};
+
+/**
+ * @class ACE_Lite_MMAP_Memory_Pool
+ *
+ * @brief Make a ``lighter-weight'' memory pool based <ACE_Mem_Map>.
+ *
+ * This implementation allows memory to be shared between
+ * processes. However, unlike the <ACE_MMAP_Memory_Pool>
+ * the <sync> methods are no-ops, which means that we don't pay
+ * for the price of flushing the memory to the backing store on
+ * every update. Naturally, this trades off increased
+ * performance for less reliability if the machine crashes.
+ */
+class ACE_Export ACE_Lite_MMAP_Memory_Pool : public ACE_MMAP_Memory_Pool
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Initialize the pool.
+ ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ virtual ~ACE_Lite_MMAP_Memory_Pool (void);
+
+ /// Overwrite the default sync behavior with no-op
+ virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
+
+ /// Overwrite the default sync behavior with no-op
+ virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
+};
+
+#if defined (ACE_WIN32)
+
+/**
+ * @class ACE_Pagefile_Memory_Pool_Options
+ *
+ * @brief Helper class for Pagefile Memory Pool constructor options.
+ *
+ * This should be a nested class, but that breaks too many
+ * compilers.
+ */
+class ACE_Export ACE_Pagefile_Memory_Pool_Options
+{
+public:
+ // Initialization method.
+ ACE_Pagefile_Memory_Pool_Options (void *base_addr = ACE_DEFAULT_PAGEFILE_POOL_BASE,
+ size_t max_size = ACE_DEFAULT_PAGEFILE_POOL_SIZE);
+
+ /// Base address of the memory-mapped backing store.
+ void *base_addr_;
+
+ /// Maximum size the pool may grow.
+ size_t max_size_;
+};
+
+/**
+ * @class ACE_Pagefile_Memory_Pool
+ *
+ * @brief Make a memory pool that is based on "anonymous" memory
+ * regions allocated from the Win32 page file.
+ */
+class ACE_Export ACE_Pagefile_Memory_Pool
+{
+public:
+ typedef ACE_Pagefile_Memory_Pool_Options OPTIONS;
+
+ /// Initialize the pool.
+ ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name = 0,
+ const OPTIONS *options = 0);
+
+ /// Ask system for initial chunk of shared memory.
+ void *init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time);
+
+ /// Acquire at least <nbytes> from the memory pool. <rounded_bytes>
+ /// is the actual number of bytes allocated.
+ void *acquire (size_t nbytes,
+ size_t &rounded_bytes);
+
+ /// Instruct the memory pool to release all of its resources.
+ int release (void);
+
+ /**
+ * Win32 Structural exception selector. The return value decides
+ * how to handle memory pool related structural exceptions. Returns
+ * 1, 0, or , -1.
+ */
+ virtual int seh_selector (void *);
+
+ /**
+ * Try to extend the virtual address space so that <addr> is now
+ * covered by the address mapping. The method succeeds and returns
+ * 0 if the backing store has adequate memory to cover this address.
+ * Otherwise, it returns -1. This method is typically called by an
+ * exception handler for a Win32 structured exception when another
+ * process has grown the backing store (and its mapping) and our
+ * process now incurs a fault because our mapping isn't in range
+ * (yet).
+ */
+ int remap (void *addr);
+
+ /// Round up to system page size.
+ size_t round_to_page_size (size_t nbytes);
+
+ /// Round up to the chunk size required by the operation system
+ size_t round_to_chunk_size (size_t nbytes);
+
+ // = Don't need this methods here ...
+ int sync (ssize_t = -1, int = MS_SYNC);
+ int sync (void *, size_t, int = MS_SYNC);
+ int protect (ssize_t = -1, int = PROT_RDWR);
+ int protect (void *, size_t, int = PROT_RDWR);
+ void dump (void) const {}
+
+protected:
+
+ /**
+ * Map portions or the entire pool into the local virtual address
+ * space. To do this, we compute the new <file_offset> of the
+ * backing store and commit the memory.
+ */
+ int map (int &firstTime, int appendBytes = 0);
+
+ /// Release the mapping.
+ int unmap (void);
+
+private:
+
+ /**
+ * @class Control_Block
+ *
+ * @brief Attributes that are meaningful in local storage only.
+ */
+ class Control_Block
+ {
+ public:
+ /// required base address
+ void *req_base_;
+
+ /// Base address returned from system call
+ void *mapped_base_;
+
+ /**
+ * @class Shared_Control_Block
+ *
+ * @brief Pool statistics
+ */
+ class Shared_Control_Block
+ {
+ public:
+ /// Maximum size the pool may grow
+ size_t max_size_;
+
+ /// Size of mapped shared memory segment
+ int mapped_size_;
+
+ /// Offset to mapped but not yet acquired address space
+ int free_offset_;
+
+ /// Size of mapped but not yet acquired address space
+ int free_size_;
+ };
+
+ Shared_Control_Block sh_;
+ };
+
+ // Base of mapped region. If this has the value of 0 then the OS is
+ // free to select any address to map the file, otherwise this value
+ // is what the OS must try to use to mmap the file.
+
+ /// Description of what our process mapped.
+ Control_Block local_cb_;
+
+ /// Shared memory pool statistics.
+ Control_Block *shared_cb_;
+
+ /// File mapping handle.
+ ACE_HANDLE object_handle_;
+
+ /// System page size.
+ size_t page_size_;
+
+ /// Name of the backing store where the shared memory pool is kept.
+ ACE_TCHAR backing_store_name_[MAXPATHLEN];
+};
+
+#endif /* ACE_WIN32 */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Memory_Pool.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_MEMORY_POOL_H */
diff --git a/ace/Memory/Memory_Pool.i b/ace/Memory/Memory_Pool.i
new file mode 100644
index 00000000000..ccb540242ce
--- /dev/null
+++ b/ace/Memory/Memory_Pool.i
@@ -0,0 +1,244 @@
+/* -*- C++ -*- */
+// $Id$
+
+ACE_INLINE
+ACE_Local_Memory_Pool::~ACE_Local_Memory_Pool (void)
+{
+ // Free up all memory allocated by this pool.
+ this->release ();
+}
+
+ACE_INLINE int
+ACE_Local_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Local_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Local_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::protect");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Local_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::protect");
+ return 0;
+}
+
+ACE_INLINE
+ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void)
+{
+}
+
+ACE_INLINE
+ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void)
+{
+}
+
+ACE_INLINE size_t
+ACE_MMAP_Memory_Pool::round_up (size_t nbytes)
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up");
+ return ACE::round_to_pagesize (nbytes);
+}
+
+ACE_INLINE void *
+ACE_MMAP_Memory_Pool::base_addr (void) const
+{
+ ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr");
+ return this->base_addr_;
+}
+
+// Ask system for initial chunk of local memory.
+
+ACE_INLINE void *
+ACE_Local_Memory_Pool::init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::init_acquire");
+ // Note that we assume that when ACE_Local_Memory_Pool is used,
+ // ACE_Malloc's constructor will only get called once. If this
+ // assumption doesn't hold, we are in deep trouble!
+
+ first_time = 1;
+ return this->acquire (nbytes, rounded_bytes);
+}
+
+// Let the underlying new operator figure out the alignment...
+
+ACE_INLINE size_t
+ACE_Local_Memory_Pool::round_up (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Local_Memory_Pool::round_up");
+ return ACE::round_to_pagesize (nbytes);
+}
+
+#if !defined (ACE_LACKS_SYSV_SHMEM)
+// Implement the algorithm for rounding up the request to an
+// appropriate chunksize.
+
+ACE_INLINE
+ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool (void)
+{
+}
+
+ACE_INLINE size_t
+ACE_Shared_Memory_Pool::round_up (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::round_up");
+ if (nbytes < this->segment_size_)
+ nbytes = this->segment_size_;
+
+ return ACE::round_to_pagesize (nbytes);
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
+ return 0;
+}
+#endif /* !ACE_LACKS_SYSV_SHMEM */
+
+#if !defined (ACE_LACKS_SBRK)
+
+ACE_INLINE
+ACE_Sbrk_Memory_Pool::~ACE_Sbrk_Memory_Pool (void)
+{
+}
+
+// Ask system for initial chunk of local memory.
+
+ACE_INLINE void *
+ACE_Sbrk_Memory_Pool::init_acquire (size_t nbytes,
+ size_t &rounded_bytes,
+ int &first_time)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::init_acquire");
+ // Note that we assume that when ACE_Sbrk_Memory_Pool is used,
+ // ACE_Malloc's constructor will only get called once. If this
+ // assumption doesn't hold, we are in deep trouble!
+
+ first_time = 1;
+ return this->acquire (nbytes, rounded_bytes);
+}
+
+// Round up the request to a multiple of the page size.
+
+ACE_INLINE size_t
+ACE_Sbrk_Memory_Pool::round_up (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::round_up");
+ return ACE::round_to_pagesize (nbytes);
+}
+
+/* No-op for now... */
+
+ACE_INLINE int
+ACE_Sbrk_Memory_Pool::release (void)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::release");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Sbrk_Memory_Pool::sync (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Sbrk_Memory_Pool::sync (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Sbrk_Memory_Pool::protect (ssize_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect");
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Sbrk_Memory_Pool::protect (void *, size_t, int)
+{
+ ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect");
+ return 0;
+}
+#endif /* !ACE_LACKS_SBRK */
+
+#if defined (ACE_WIN32)
+
+ACE_INLINE size_t
+ACE_Pagefile_Memory_Pool::round_to_chunk_size (size_t nbytes)
+{
+ return (nbytes + ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1)
+ & (~(ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1));
+}
+
+ACE_INLINE size_t
+ACE_Pagefile_Memory_Pool::round_to_page_size (size_t nbytes)
+{
+ return ACE::round_to_pagesize (nbytes);
+}
+
+ACE_INLINE int
+ACE_Pagefile_Memory_Pool::sync (ssize_t, int)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Pagefile_Memory_Pool::sync (void *, size_t, int)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Pagefile_Memory_Pool::protect (ssize_t, int)
+{
+ return 0;
+}
+
+ACE_INLINE int
+ACE_Pagefile_Memory_Pool::protect (void *, size_t, int)
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ace/Memory/Obchunk.cpp b/ace/Memory/Obchunk.cpp
new file mode 100644
index 00000000000..5143a07a20c
--- /dev/null
+++ b/ace/Memory/Obchunk.cpp
@@ -0,0 +1,30 @@
+// $Id$
+
+#include "ace/Obchunk.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Obchunk.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Obchunk, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Obchunk)
+
+void
+ACE_Obchunk::dump (void) const
+{
+ ACE_TRACE ("ACE_Obchunk::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("end_ = %x\n"), this->end_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("cur_ = %x\n"), this->cur_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_Obchunk::ACE_Obchunk (size_t size)
+ : end_ (contents_ + size),
+ block_ (contents_),
+ cur_ (contents_),
+ next_ (0)
+{
+}
diff --git a/ace/Memory/Obchunk.h b/ace/Memory/Obchunk.h
new file mode 100644
index 00000000000..9259b97a7a0
--- /dev/null
+++ b/ace/Memory/Obchunk.h
@@ -0,0 +1,72 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Obchunk.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_OBCHUNK_H
+#define ACE_OBCHUNK_H
+#include "ace/pre.h"
+
+#include "ace/Malloc.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Obchunk
+ *
+ * @brief Defines the state that represents a "chunk" of memory.
+ * Evenything in this class is public because it is designed
+ * as an internal structure of Obstack_T and users are
+ * not supposed to use this class directly.
+ * @sa ACE_Obstack_T
+ */
+class ACE_Export ACE_Obchunk
+{
+public:
+ /// Constructor.
+ ACE_Obchunk (size_t size);
+
+ /// Dtor.
+ ~ACE_Obchunk (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Pointer to the end of the chunk.
+ char *end_;
+
+ /// Pointer to the head of the current building block.
+ char *block_;
+
+ /// Pointer to the current location in the chunk.
+ char *cur_;
+
+ /// Next chunk in the chain.
+ ACE_Obchunk *next_;
+
+ /**
+ * Pointer to the beginning contents of this chunk. This field is
+ * actually overlayed by the memory allocated by
+ * <ACE_Obstack::new_chunk>. Therefore, it *must* come last.
+ */
+ char contents_[4];
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Obchunk.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_OBCHUNK_H */
diff --git a/ace/Memory/Obchunk.i b/ace/Memory/Obchunk.i
new file mode 100644
index 00000000000..510c511d4f9
--- /dev/null
+++ b/ace/Memory/Obchunk.i
@@ -0,0 +1,9 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Obchunk.i
+
+ACE_INLINE
+ACE_Obchunk::~ACE_Obchunk (void)
+{
+}
diff --git a/ace/Memory/Obstack.cpp b/ace/Memory/Obstack.cpp
new file mode 100644
index 00000000000..d794f1263fe
--- /dev/null
+++ b/ace/Memory/Obstack.cpp
@@ -0,0 +1,11 @@
+// $Id$
+
+#include "ace/Obstack.h"
+
+ACE_RCSID(ace, Obstack, "$Id$")
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Obstack_T<char>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Obstack_T<char>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Memory/Obstack.h b/ace/Memory/Obstack.h
new file mode 100644
index 00000000000..a6732bbb290
--- /dev/null
+++ b/ace/Memory/Obstack.h
@@ -0,0 +1,28 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Obstack.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_OBSTACK_H
+#define ACE_OBSTACK_H
+#include "ace/pre.h"
+
+#include "ace/Obstack_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+typedef ACE_Obstack_T<char> ACE_Obstack;
+
+ACE_SINGLETON_DECLARATION (ACE_Obstack_T <char>;)
+
+#include "ace/post.h"
+#endif /* ACE_OBSTACK_H */
diff --git a/ace/Memory/Obstack_T.cpp b/ace/Memory/Obstack_T.cpp
new file mode 100644
index 00000000000..cd80fb23c66
--- /dev/null
+++ b/ace/Memory/Obstack_T.cpp
@@ -0,0 +1,163 @@
+// $Id$
+
+#include "ace/Obstack_T.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Obstack_T.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Obstack_T, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Obstack_T)
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::dump (void) const
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("size_ = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("head_ = %x\n"), this->head_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("curr_ = %x\n"), this->curr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <class CHAR> int
+ACE_Obstack_T<CHAR>::request (size_t len)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::request");
+
+ // normalize the length.
+ len *= sizeof (CHAR);
+
+ // We will always have enough room for null terminating char
+ // unless sizeof (char) > 4.
+ // There's no way we can handle more than this->size_ of strings.
+ if (this->size_ < len)
+ return -1;
+
+ // Check whether we need to grow our chunk...
+ if (this->curr_->cur_ + len >= this->curr_->end_)
+ {
+ ACE_Obchunk *temp = this->curr_;
+ if (this->curr_->next_ == 0)
+ {
+ // We must allocate new memory.
+ this->curr_->next_ = this->new_chunk ();
+ this->curr_ = this->curr_->next_;
+ }
+ else
+ {
+ // We can reuse previously allocated memory.
+ this->curr_ = this->curr_->next_;
+ this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_;
+ }
+
+ // if there are something in there already.
+ if (temp->cur_ != temp->block_)
+ {
+ // @@ Require pointer arithmatic?
+ size_t datasize = temp->cur_ - temp->block_;
+
+ // Check the total length of data again.
+ if (this->size_ < len + datasize)
+ return -1;
+
+ ACE_OS::memcpy (this->curr_->block_,
+ temp->block_,
+ datasize);
+ this->curr_->cur_ = this->curr_->block_ + datasize;
+ }
+ }
+
+ return 0;
+}
+
+template <class CHAR> CHAR *
+ACE_Obstack_T<CHAR>::grow (CHAR c)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::grow");
+
+ if (this->request (1) == 0)
+ {
+ CHAR *retv = ACE_reinterpret_cast (CHAR *,
+ this->curr_->cur_);
+ this->curr_->cur_ += sizeof (CHAR);
+ *retv = c;
+ return retv;
+ }
+ else
+ return 0;
+}
+
+template <class CHAR> ACE_Obchunk *
+ACE_Obstack_T<CHAR>::new_chunk (void)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::new_chunk");
+
+ ACE_Obchunk *temp;
+
+ ACE_NEW_MALLOC_RETURN (temp,
+ ACE_static_cast (ACE_Obchunk *,
+ this->allocator_strategy_->malloc
+ (sizeof (class ACE_Obchunk) + this->size_)),
+ ACE_Obchunk (this->size_),
+ 0);
+ return temp;
+}
+
+template <class CHAR>
+ACE_Obstack_T<CHAR>::ACE_Obstack_T (size_t size,
+ ACE_Allocator *allocator_strategy)
+ : allocator_strategy_ (allocator_strategy),
+ size_ (size)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::ACE_Obstack");
+
+ if (this->allocator_strategy_ == 0)
+ ACE_ALLOCATOR (this->allocator_strategy_,
+ ACE_Allocator::instance ());
+
+ this->head_ = this->new_chunk ();
+ this->curr_ = this->head_;
+}
+
+template <class CHAR>
+ACE_Obstack_T<CHAR>::~ACE_Obstack_T (void)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::~ACE_Obstack_T");
+
+ ACE_Obchunk *temp = this->head_;
+
+ while (temp != 0)
+ {
+ ACE_Obchunk *next = temp->next_;
+ temp->next_ = 0;
+ this->allocator_strategy_->free ((void *) temp);
+ temp = next;
+ }
+}
+
+template <class CHAR> CHAR *
+ACE_Obstack_T<CHAR>::copy (const CHAR *s,
+ size_t len)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::copy");
+
+ if (this->request (len) != 0)
+ return 0;
+
+ size_t tsize = len * sizeof (CHAR);
+ ACE_OS::memcpy (this->curr_->cur_, s, tsize);
+ this->curr_->cur_ += tsize ;
+ return this->freeze ();
+}
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::release (void)
+{
+ ACE_TRACE ("ACE_Obstack_T<CHAR>::release");
+
+ this->curr_ = this->head_;
+ this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_;
+}
diff --git a/ace/Memory/Obstack_T.h b/ace/Memory/Obstack_T.h
new file mode 100644
index 00000000000..0cf272b3dd0
--- /dev/null
+++ b/ace/Memory/Obstack_T.h
@@ -0,0 +1,114 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Obstack_T.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt, Nanbor Wang
+ */
+//=============================================================================
+
+
+#ifndef ACE_OBSTACK_T_H
+#define ACE_OBSTACK_T_H
+#include "ace/pre.h"
+
+#include "ace/Obchunk.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+/**
+ * @class ACE_Obstack
+ *
+ * @brief Define a simple "mark and release" memory allocation utility.
+ *
+ * The implementation is similar to the GNU obstack utility,
+ * which is used extensively in the GCC compiler.
+ */
+template <class CHAR>
+class ACE_Obstack_T
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Obstack_T (size_t size = (4096 * sizeof (CHAR)) - sizeof (ACE_Obchunk),
+ ACE_Allocator *allocator_strategy = 0);
+ ~ACE_Obstack_T (void);
+
+ /// Request Obstack to prepare a block at least @a len long for building
+ /// a new string. Return -1 if fail, 0 if success.
+ int request (size_t len);
+
+ /// Inserting a new CHAR \a c into the current building
+ /// block without freezing (null terminating) the block.
+ /// This function will create new chunk by checking the
+ /// boundary of current Obchunk. Return
+ /// the location \a c gets inserted to, or 0 if error.
+ CHAR *grow (CHAR c);
+
+ /// Inserting a new CHAR \a c into the current building
+ /// block without freezing (null terminating) the block and without
+ /// checking for out-of-bound error.
+ void grow_fast (CHAR c);
+
+ /// Freeze the current building block by null terminating it.
+ /// Return the starting address of the current building block, 0
+ /// if error occurs.
+ CHAR *freeze (void);
+
+ /// Copy the data into the current Obchunk and freeze the current
+ /// block. Return the starting address of the current building
+ /// block, 0 if error occurs. @a len specify the string length,
+ /// not the actually data size.
+ CHAR *copy (const CHAR *data,
+ size_t len);
+
+ /// Return the maximum @a length or @a size of a string that can be put into
+ /// this Obstack. @a size = @a length * sizeof (CHAR).
+ size_t length (void) const;
+ size_t size (void) const;
+
+ /// "Release" the entire stack of Obchunks, putting it back on the
+ /// free list.
+ void release (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ class ACE_Obchunk *new_chunk (void);
+
+ /// Pointer to the allocator used by this Obstack.
+ ACE_Allocator *allocator_strategy_;
+
+ /// Current size of the Obstack;
+ size_t size_;
+
+ // Don't change the order of the following two fields.
+ /// Head of the Obchunk chain.
+ class ACE_Obchunk *head_;
+
+ /// Pointer to the current Obchunk.
+ class ACE_Obchunk *curr_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Obstack_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Obstack_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Obstack_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_OBSTACK_T_H */
diff --git a/ace/Memory/Obstack_T.i b/ace/Memory/Obstack_T.i
new file mode 100644
index 00000000000..f6ff337ba6e
--- /dev/null
+++ b/ace/Memory/Obstack_T.i
@@ -0,0 +1,33 @@
+// $Id$
+
+template <class CHAR> ACE_INLINE size_t
+ACE_Obstack_T<CHAR>::length () const
+{
+ return this->size_ / sizeof (CHAR);
+}
+
+template <class CHAR> ACE_INLINE size_t
+ACE_Obstack_T<CHAR>::size () const
+{
+ return this->size_;
+}
+
+template <class CHAR> ACE_INLINE void
+ACE_Obstack_T<CHAR>::grow_fast (CHAR c)
+{
+ * (ACE_reinterpret_cast (CHAR *,
+ this->curr_->cur_)) = c;
+ this->curr_->cur_ += sizeof (CHAR);
+}
+
+template <class CHAR> ACE_INLINE CHAR *
+ACE_Obstack_T<CHAR>::freeze (void)
+{
+ CHAR *retv = ACE_reinterpret_cast (CHAR *, this->curr_->block_);
+ * (ACE_reinterpret_cast (CHAR *,
+ this->curr_->cur_)) = 0;
+
+ this->curr_->cur_ += sizeof (CHAR);
+ this->curr_->block_ = this->curr_->cur_;
+ return retv;
+}
diff --git a/ace/Memory/PI_Malloc.cpp b/ace/Memory/PI_Malloc.cpp
new file mode 100644
index 00000000000..8299304f4fb
--- /dev/null
+++ b/ace/Memory/PI_Malloc.cpp
@@ -0,0 +1,176 @@
+// $Id$
+
+// FILENAME
+// PI_Malloc.cpp
+//
+// AUTHOR
+// Priyanka Gontla <pgontla@ece.uci.edu>
+//
+// =========================================================================
+
+#if !defined (ACE_PI_MALLOC_CPP)
+#define ACE_PI_MALLOC_CPP
+
+#include "ace/PI_Malloc.h"
+#include "ace/Object_Manager.h"
+#include "ace/Process_Mutex.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/PI_Malloc.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/Synch_T.h"
+
+ACE_RCSID(ace, PI_Malloc, "$Id$")
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+void
+ACE_PI_Control_Block::ACE_Malloc_Header::dump (void) const
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Malloc_Header::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnext_block = %x"), (ACE_Malloc_Header *) this->next_block_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize = %d\n"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+void
+ACE_PI_Control_Block::print_alignment_info (void)
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Control_Block::print_alignment_info");
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Start ---> ACE_PI_Control_Block::print_alignment_info:\n")));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("Sizeof ptr: %d\n")
+ ACE_LIB_TEXT ("Sizeof size_t: %d\n")
+ ACE_LIB_TEXT ("Sizeof long: %d\n")
+ ACE_LIB_TEXT ("Sizeof double: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_MALLOC_ALIGN: %d\n")
+ ACE_LIB_TEXT ("sizeof ACE_MALLOC_PADDING: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_MALLOC_HEADER_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_PI_MALLOC_PADDING_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_PI_CONTROL_BLOCK_SIZE: %d\n")
+ ACE_LIB_TEXT ("Sizeof ACE_PI_CONTROL_BLOCK_ALIGN_LONGS: %d\n")
+ ACE_LIB_TEXT ("Sizeof (MALLOC_HEADER): %d\n")
+ ACE_LIB_TEXT ("Sizeof (CONTROL_BLOCK): %d\n"),
+ sizeof (char *),
+ sizeof (size_t),
+ sizeof (long),
+ sizeof (double),
+ ACE_MALLOC_ALIGN,
+ ACE_MALLOC_PADDING,
+ ACE_MALLOC_HEADER_SIZE,
+ ACE_PI_MALLOC_PADDING_SIZE,
+ ACE_PI_CONTROL_BLOCK_SIZE,
+ ACE_PI_CONTROL_BLOCK_ALIGN_LONGS,
+ sizeof (ACE_Malloc_Header),
+ sizeof (ACE_PI_Control_Block)
+ ));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("End <--- ACE_PI_Control_Block::print_alignment_info:\n")));
+}
+
+void
+ACE_PI_Control_Block::dump (void) const
+{
+ ACE_TRACE ("ACE_PI_Control_Block::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("Name Node:\n")));
+ for (ACE_Name_Node *nextn = this->name_head_;
+ nextn != 0;
+ nextn = nextn->next_)
+ nextn->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("freep_ = %x"), (ACE_Malloc_Header *) this->freep_));
+ this->base_.dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nMalloc Header:\n")));
+ for (ACE_Malloc_Header *nexth = ((ACE_Malloc_Header *)this->freep_)->next_block_;
+ nexth != 0 && nexth != &this->base_;
+ nexth = nexth->next_block_)
+ nexth->dump ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node (void)
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node");
+}
+
+ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node (const char *name,
+ char *name_ptr,
+ char *pointer,
+ ACE_Name_Node *next)
+ : name_ (name_ptr),
+ pointer_ (pointer),
+ next_ (next),
+ prev_ (0)
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node");
+ char *n = this->name_;
+ ACE_OS::strcpy (n, name);
+ if (next != 0)
+ next->prev_ = this;
+}
+
+ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node (const ACE_Name_Node &)
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Name_Node::ACE_Name_Node");
+ ACE_ASSERT (0); // not implemented!
+}
+
+const char *
+ACE_PI_Control_Block::ACE_Name_Node::name (void) const
+{
+ const char *c = this->name_;
+ return c;
+}
+
+void
+ACE_PI_Control_Block::ACE_Name_Node::name (const char *)
+{
+ ACE_ASSERT (0); // not implemented yet.
+}
+
+ACE_PI_Control_Block::ACE_Malloc_Header::ACE_Malloc_Header (void)
+ : next_block_ (0),
+ size_ (0)
+{
+}
+
+void
+ACE_PI_Control_Block::ACE_Name_Node::dump (void) const
+{
+ ACE_TRACE ("ACE_PI_Control_Block::ACE_Name_Node::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("pointer = %x"), (const char *) this->pointer_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\nnext_ = %x"), (ACE_Name_Node *) this->next_));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT("\nname_ = (%x, %s)"),
+ (const char *) this->name_,
+ (const char *) this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Based_Pointer_Basic<ACE_PI_Control_Block::ACE_Malloc_Header>;
+template class ACE_Based_Pointer_Basic<ACE_PI_Control_Block::ACE_Name_Node>;
+template class ACE_Based_Pointer_Basic<char>;
+template class ACE_Based_Pointer<ACE_PI_Control_Block::ACE_Malloc_Header>;
+template class ACE_Based_Pointer<ACE_PI_Control_Block::ACE_Name_Node>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Based_Pointer_Basic<ACE_PI_Control_Block::ACE_Malloc_Header>
+#pragma instantiate ACE_Based_Pointer_Basic<ACE_PI_Control_Block::ACE_Name_Node>
+#pragma instantiate ACE_Based_Pointer_Basic<char>
+#pragma instantiate ACE_Based_Pointer<ACE_PI_Control_Block::ACE_Malloc_Header>
+#pragma instantiate ACE_Based_Pointer<ACE_PI_Control_Block::ACE_Name_Node>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1*/
+
+#endif /* ACE_PI_MALLOC_CPP */
diff --git a/ace/Memory/PI_Malloc.h b/ace/Memory/PI_Malloc.h
new file mode 100644
index 00000000000..fcb0b0bbb75
--- /dev/null
+++ b/ace/Memory/PI_Malloc.h
@@ -0,0 +1,213 @@
+
+//=============================================================================
+/**
+ * @file PI_Malloc.h
+ *
+ * $Id$
+ *
+ * @author Priyanka Gontla <pgontla@ece.uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_PI_MALLOC_H
+#define ACE_PI_MALLOC_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+#include "Malloc.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+#include "ace/Based_Pointer_T.h"
+
+// prepare for position independent malloc
+/**
+ * @class ACE_PI_Control_Block
+ *
+ * @brief This information is stored in memory allocated by the <Memory_Pool>.
+ *
+ * This class implements the control block structure that can be
+ * used in a "position indepent" fashion, i.e., you don't need to
+ * "map" the underlying memory pool to the same address in
+ * processes sharing the memory. The tradoff of this flexibility
+ * is more expensive malloc/free operations.
+ */
+class ACE_Export ACE_PI_Control_Block
+{
+public:
+ class ACE_Malloc_Header;
+ class ACE_Name_Node;
+
+ typedef ACE_Based_Pointer<ACE_Malloc_Header> MALLOC_HEADER_PTR;
+ typedef ACE_Based_Pointer<ACE_Name_Node> NAME_NODE_PTR;
+ typedef ACE_Based_Pointer_Basic<char> CHAR_PTR;
+
+ /**
+ * @class ACE_Malloc_Header
+ *
+ * @brief This is the control block header. It's used by <ACE_Malloc>
+ * to keep track of each chunk of data when it's in the free
+ * list or in use.
+ */
+ class ACE_Export ACE_Malloc_Header
+ {
+ public:
+ ACE_Malloc_Header (void);
+
+ /// Points to next block if on free list.
+ MALLOC_HEADER_PTR next_block_;
+
+ /// Initialize a malloc header pointer.
+ static void init_ptr (MALLOC_HEADER_PTR *ptr,
+ ACE_Malloc_Header *init,
+ void *base_addr);
+
+ /// Size of this header control block.
+ size_t size_;
+
+#if defined (ACE_PI_MALLOC_PADDING_SIZE) && (ACE_PI_MALLOC_PADDING_SIZE == 0)
+ // No padding required for PI_Malloc_Header.
+#else
+# if !defined (ACE_PI_MALLOC_PADDING_SIZE)
+# define ACE_PI_MALLOC_PADDING_SIZE ((int) (ACE_MALLOC_HEADER_SIZE - \
+ (sizeof (MALLOC_HEADER_PTR) + sizeof (size_t)))\
+ / (int) sizeof (long))
+# endif /* !ACE_PI_MALLOC_PADDING_SIZE */
+ long padding_[ACE_PI_MALLOC_PADDING_SIZE < 1 ? 1 : ACE_PI_MALLOC_PADDING_SIZE];
+#endif /* ACE_PI_MALLOC_PADDING_SIZE && ACE_PI_MALLOC_PADDING_SIZE == 0 */
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+ private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Malloc_Header &))
+ };
+
+ /**
+ * @class ACE_Name_Node
+ *
+ * @brief This class supports "named memory regions" within <ACE_Malloc>.
+ *
+ * Internally, the named memory regions are stored as a
+ * doubly-linked list within the <Memory_Pool>. This makes
+ * it easy to iterate over the items in the list in both FIFO
+ * and LIFO order.
+ */
+ class ACE_Export ACE_Name_Node
+ {
+ public:
+ // = Initialization methods.
+ /// Constructor.
+ ACE_Name_Node (const char *name,
+ char *name_ptr,
+ char *pointer,
+ ACE_Name_Node *head);
+
+ /// Copy constructor.
+ ACE_Name_Node (const ACE_Name_Node &);
+
+ /// Constructor.
+ ACE_Name_Node (void);
+
+ /// Constructor.
+ ~ACE_Name_Node (void);
+
+ /// Initialize a name node pointer.
+ static void init_ptr (NAME_NODE_PTR *ptr,
+ ACE_Name_Node *init,
+ void *base_addr);
+
+ /// Return a pointer to the name of this node.
+ const char *name (void) const;
+
+ /// Assign a name;
+ void name (const char *);
+
+ /// Name of the Node.
+ CHAR_PTR name_;
+
+ /// Pointer to the contents.
+ CHAR_PTR pointer_;
+
+ /// Pointer to the next node in the doubly-linked list.
+ NAME_NODE_PTR next_;
+
+ /// Pointer to the previous node in the doubly-linked list.
+ NAME_NODE_PTR prev_;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+ private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Name_Node &))
+ };
+
+ /// Print out a bunch of size info for debugging.
+ static void print_alignment_info (void);
+
+ /// Reference counter.
+ int ref_counter_;
+
+ /// Head of the linked list of Name Nodes.
+ NAME_NODE_PTR name_head_;
+
+ /// Current head of the freelist.
+ MALLOC_HEADER_PTR freep_;
+
+ /// Name of lock thats ensures mutual exclusion.
+ char lock_name_[MAXNAMELEN];
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ /// Keep statistics about ACE_Malloc state and performance.
+ ACE_Malloc_Stats malloc_stats_;
+#define ACE_PI_CONTROL_BLOCK_SIZE ((int)(sizeof (NAME_NODE_PTR) \
+ + sizeof (MALLOC_HEADER_PTR) \
+ + sizeof (int) \
+ + MAXNAMELEN \
+ + sizeof (ACE_Malloc_Stats)))
+#else
+#define ACE_PI_CONTROL_BLOCK_SIZE ((int)(sizeof (NAME_NODE_PTR) \
+ + sizeof (MALLOC_HEADER_PTR) \
+ + sizeof (int) \
+ + MAXNAMELEN))
+#endif /* ACE_HAS_MALLOC_STATS */
+
+#if defined (ACE_PI_CONTROL_BLOCK_ALIGN_LONGS) && (ACE_PI_CONTROL_BLOCK_ALIGN_LONGS == 0)
+ // No padding required for PI_Control_Block.
+#else
+# if !defined (ACE_PI_CONTROL_BLOCK_ALIGN_LONGS)
+// Notice the casting to int for <sizeof> otherwise unsigned int
+// arithmetic is used and some awful things may happen.
+# define ACE_PI_CONTROL_BLOCK_ALIGN_LONGS \
+ ((ACE_PI_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN != 0 \
+ ? ACE_MALLOC_ALIGN - (ACE_PI_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN) \
+ : ACE_MALLOC_ALIGN) / int (sizeof (long)))
+# endif /* !ACE_PI_CONTROL_BLOCK_ALIGN_LONGS */
+ /// Force alignment.
+ long align_[ACE_PI_CONTROL_BLOCK_ALIGN_LONGS < 1 ? 1 : ACE_PI_CONTROL_BLOCK_ALIGN_LONGS];
+#endif /* ACE_PI_CONTROL_BLOCK_ALIGN_LONGS && ACE_PI_CONTROL_BLOCK_ALIGN_LONGS == 0 */
+
+ /// Dummy node used to anchor the freelist. This needs to come last...
+ ACE_Malloc_Header base_;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Control_Block &))
+};
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+#if defined (__ACE_INLINE__)
+#include "ace/PI_Malloc.i"
+#endif /* __ACE_INLINE__ */
+
+// Include the ACE_Malloc templates and ACE_Memory_Pool classes at this point.
+#include "ace/Malloc_T.h"
+#include "ace/Memory_Pool.h"
+
+#include "ace/post.h"
+#endif /* ACE_PI_MALLOC_H */
diff --git a/ace/Memory/PI_Malloc.i b/ace/Memory/PI_Malloc.i
new file mode 100644
index 00000000000..b082b523618
--- /dev/null
+++ b/ace/Memory/PI_Malloc.i
@@ -0,0 +1,25 @@
+// $Id$
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+ACE_INLINE
+ACE_PI_Control_Block::ACE_Name_Node::~ACE_Name_Node (void)
+{
+}
+
+ACE_INLINE void
+ACE_PI_Control_Block::ACE_Malloc_Header::init_ptr
+ (MALLOC_HEADER_PTR *ptr, ACE_Malloc_Header *init, void *base_addr)
+{
+ new ((void *) ptr) MALLOC_HEADER_PTR (base_addr, 0);
+ *ptr = init;
+}
+
+ACE_INLINE void
+ACE_PI_Control_Block::ACE_Name_Node::init_ptr
+ (NAME_NODE_PTR *ptr, ACE_Name_Node *init, void *base_addr)
+{
+ new ((void *) ptr) NAME_NODE_PTR (base_addr, 0);
+ *ptr = init;
+}
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
diff --git a/ace/Memory/Read_Buffer.cpp b/ace/Memory/Read_Buffer.cpp
new file mode 100644
index 00000000000..2b88461446e
--- /dev/null
+++ b/ace/Memory/Read_Buffer.cpp
@@ -0,0 +1,162 @@
+// $Id$
+
+#include "ace/Read_Buffer.h"
+#include "ace/Service_Config.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Read_Buffer.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Read_Buffer, "$Id$")
+
+void
+ACE_Read_Buffer::dump (void) const
+{
+ ACE_TRACE ("ACE_Read_Buffer::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("size_ = %d"), this->size_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\noccurrences_ = %d"), this->occurrences_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nstream_ = %x"), this->stream_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nallocator_ = %x"), this->allocator_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_Read_Buffer::ACE_Read_Buffer (FILE *fp,
+ int close_on_delete,
+ ACE_Allocator *alloc)
+ : stream_ (fp),
+ close_on_delete_ (close_on_delete),
+ allocator_ (alloc)
+{
+ ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer");
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+}
+
+ACE_Read_Buffer::ACE_Read_Buffer (ACE_HANDLE handle,
+ int close_on_delete,
+ ACE_Allocator *alloc)
+ : stream_ (ACE_OS::fdopen (handle, ACE_LIB_TEXT ("r"))),
+ close_on_delete_ (close_on_delete),
+ allocator_ (alloc)
+{
+ ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer");
+
+ if (this->allocator_ == 0)
+ this->allocator_ = ACE_Allocator::instance ();
+}
+
+ACE_Read_Buffer::~ACE_Read_Buffer (void)
+{
+ ACE_TRACE ("ACE_Read_Buffer::~ACE_Read_Buffer");
+
+ if (this->close_on_delete_)
+ ACE_OS::fclose (this->stream_);
+}
+
+// Input: term the character to terminate on
+// search the character to search for
+// replace the character with which to replace search
+// Output: a buffer containing the contents of stream
+// Method: call the recursive helper function read_helper
+
+char *
+ACE_Read_Buffer::read (int term, int search, int replace)
+{
+ ACE_TRACE ("ACE_Read_Buffer::read");
+ this->occurrences_ = 0;
+ this->size_ = 0;
+ return this->rec_read (term, search, replace);
+}
+
+// Input: term the termination character
+// search the character to search for
+// replace the character with which to replace search
+// Purpose: read in a file to a buffer using only a single dynamic
+// allocation.
+// Method: read until the local buffer is full and then recurse.
+// Must continue until the termination character is reached.
+// Allocate the final buffer based on the number of local
+// buffers read and as the recursive calls bottom out,
+// copy them in reverse order into the allocated buffer.
+
+char *
+ACE_Read_Buffer::rec_read (int term, int search, int replace)
+{
+ ACE_TRACE ("ACE_Read_Buffer::rec_read");
+ // This is our temporary workspace.
+ char buf[BUFSIZ];
+
+ int c = EOF;
+ size_t slot = 0;
+ int done = 0;
+
+ // Read in the file char by char
+ while (slot < BUFSIZ)
+ {
+ c = getc (this->stream_);
+
+ // Don't insert EOF into the buffer...
+ if (c == EOF)
+ {
+ ungetc (c, this->stream_);
+ break;
+ }
+ else if (c == term)
+ done = 1;
+
+ // Check for possible substitutions.
+ if (c == search)
+ {
+ this->occurrences_++;
+
+ if (replace >= 0)
+ c = replace;
+ }
+
+ buf[slot++] = (char) c;
+
+ // Substitutions must be made before checking for termination.
+ if (done)
+ break;
+ }
+
+ // Increment the number of bytes.
+ this->size_ += slot;
+
+ // Don't bother going any farther if the total size is 0.
+ if (this->size_ == 0)
+ return 0;
+
+ char *result;
+
+ // Recurse, when the recursion bottoms out, allocate the result
+ // buffer.
+ if (done || c == EOF)
+ {
+ // Use the allocator to acquire the memory. The + 1 allows
+ // space for the null terminator.
+ result = (char *) this->allocator_->malloc (this->size_ + 1);
+
+ if (result == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ result += this->size_;
+
+ // Null terminate the buffer.
+ *result = '\0';
+ }
+ else if ((result = this->rec_read (term, search, replace)) == 0)
+ return 0;
+
+
+ // Copy buf into the appropriate location starting from end of
+ // buffer. Peter says this is confusing and that we should use
+ // memcpy() ;-)
+ for (size_t j = slot; j > 0; j--)
+ *--result = buf[j - 1];
+
+ return result;
+}
diff --git a/ace/Memory/Read_Buffer.h b/ace/Memory/Read_Buffer.h
new file mode 100644
index 00000000000..ad1bef9fa32
--- /dev/null
+++ b/ace/Memory/Read_Buffer.h
@@ -0,0 +1,114 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Read_Buffer.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt and Seth Widoff
+ */
+//=============================================================================
+
+
+#ifndef ACE_READ_BUFFER_H
+#define ACE_READ_BUFFER_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc.h"
+
+/**
+ * @class ACE_Read_Buffer
+ *
+ * @brief Efficiently reads an artibrarily large buffer from an input
+ * stream up to and including a termination character. Also
+ * performs search/replace on single occurrences a character in
+ * the buffer using the principles of Integrated Layer
+ * Processing.
+ *
+ * This implementation is optimized to do a single dynamic
+ * allocation and make only one copy of the data. It uses
+ * recursion and the run-time stack to accomplish this
+ * efficiently.
+ */
+class ACE_Export ACE_Read_Buffer
+{
+public:
+ // = Initialization and termination methods.
+ /// Read from a FILE *.
+ ACE_Read_Buffer (FILE *fp,
+ int close_on_delete = 0,
+ ACE_Allocator * = 0);
+
+ /// Read from an open HANDLE.
+ ACE_Read_Buffer (ACE_HANDLE handle,
+ int close_on_delete = 0,
+ ACE_Allocator * = 0);
+
+ /// Closes the FILE *.
+ ~ACE_Read_Buffer (void);
+
+ /**
+ * Returns a pointer dynamically allocated with
+ * <ACE_Allocator::malloc> to data from the input stream up to (and
+ * including) the <terminator>. If <search> is >= 0 then all
+ * occurrences of the <search> value are substituted with the
+ * <replace> value. The last of the byte of data is a 0, so that
+ * <strlen> can be used on it. The caller is responsible for
+ * freeing the pointer returned from this method using the
+ * <ACE_Allocator::free>.
+ */
+ char *read (int terminator = EOF,
+ int search = '\n',
+ int replace = '\0');
+
+ /// Returns the number of characters replaced during a <read>.
+ size_t replaced (void) const;
+
+ /// Returns the size of the allocated buffer obtained during a
+ /// <read>, not including the null terminator.
+ size_t size (void) const;
+
+ /// Returns a pointer to its allocator.
+ ACE_Allocator *alloc (void) const;
+
+ /// Dump the state of the object.
+ void dump (void) const;
+
+private:
+ /// Recursive helper method that does the work...
+ char *rec_read (int term, int search, int replace);
+
+ /// The total number of characters in the buffer.
+ size_t size_;
+
+ /// The total number of characters replaced.
+ size_t occurrences_;
+
+ /// The stream we are reading from.
+ FILE *stream_;
+
+ /// Keeps track of whether we should close the FILE in the
+ /// destructor.
+ int close_on_delete_;
+
+ /// Pointer to the allocator.
+ ACE_Allocator *allocator_;
+
+ // = Disallow copying and assignment...
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Read_Buffer &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Read_Buffer (const ACE_Read_Buffer &))
+};
+
+#if defined (__ACE_INLINE__)
+# include "ace/Read_Buffer.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_READ_BUFFER_H */
diff --git a/ace/Memory/Read_Buffer.i b/ace/Memory/Read_Buffer.i
new file mode 100644
index 00000000000..3534c62db2e
--- /dev/null
+++ b/ace/Memory/Read_Buffer.i
@@ -0,0 +1,28 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Accessor to the number of bytes in the buffer.
+
+ACE_INLINE size_t
+ACE_Read_Buffer::size (void) const
+{
+ ACE_TRACE ("ACE_Read_Buffer::size");
+ return this->size_;
+}
+
+// The total number of characters replaced.
+
+ACE_INLINE size_t
+ACE_Read_Buffer::replaced (void) const
+{
+ ACE_TRACE ("ACE_Read_Buffer::replaced");
+ return this->occurrences_;
+}
+
+ACE_INLINE ACE_Allocator *
+ACE_Read_Buffer::alloc (void) const
+{
+ ACE_TRACE ("ACE_Read_Buffer::alloc");
+ return this->allocator_;
+}
+
diff --git a/ace/Memory/Shared_Memory.cpp b/ace/Memory/Shared_Memory.cpp
new file mode 100644
index 00000000000..5e4447075ee
--- /dev/null
+++ b/ace/Memory/Shared_Memory.cpp
@@ -0,0 +1,9 @@
+// $Id$
+
+#include "ace/Shared_Memory.h"
+
+ACE_RCSID(ace, Shared_Memory, "$Id$")
+
+ACE_Shared_Memory::~ACE_Shared_Memory (void)
+{
+}
diff --git a/ace/Memory/Shared_Memory.h b/ace/Memory/Shared_Memory.h
new file mode 100644
index 00000000000..b97d92e2af8
--- /dev/null
+++ b/ace/Memory/Shared_Memory.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+
+
+//=============================================================================
+/**
+ * @file Shared_Memory.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SHARED_MEMORY_H
+#define ACE_SHARED_MEMORY_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Shared_Memory
+ *
+ * @brief This base class adapts both System V shared memory and "BSD"
+ * mmap to a common API.
+ *
+ * This is a very simple-minded wrapper, i.e., it really is only
+ * useful for allocating large contiguous chunks of shared
+ * memory. For a much more sophisticated version, please check
+ * out the <ACE_Malloc> class.
+ */
+class ACE_Export ACE_Shared_Memory
+{
+public:
+ virtual ~ACE_Shared_Memory (void);
+
+ // = Note that all the following methods are pure virtual.
+ virtual int close (void) = 0;
+ virtual int remove (void) = 0;
+ virtual void *malloc (size_t = 0) = 0;
+ virtual int free (void *p) = 0;
+ virtual int get_segment_size (void) const = 0;
+ virtual ACE_HANDLE get_id (void) const = 0;
+};
+
+#include "ace/post.h"
+#endif /* ACE_SHARED_MEMORY_H */
diff --git a/ace/Memory/Shared_Memory_MM.cpp b/ace/Memory/Shared_Memory_MM.cpp
new file mode 100644
index 00000000000..85778fbdf07
--- /dev/null
+++ b/ace/Memory/Shared_Memory_MM.cpp
@@ -0,0 +1,52 @@
+// Shared_Memory_MM.cpp
+// $Id$
+
+#include "ace/Shared_Memory_MM.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_MM.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Shared_Memory_MM, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_MM)
+
+void
+ACE_Shared_Memory_MM::dump (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::dump");
+}
+
+// Creates a shared memory segment of SIZE bytes.
+
+ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (ACE_HANDLE handle,
+ int length,
+ int prot,
+ int share,
+ char *addr,
+ off_t pos)
+ : shared_memory_ (handle, length, prot, share, addr, pos)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM");
+}
+
+ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (const ACE_TCHAR *file_name,
+ int len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ char *addr,
+ off_t pos)
+ : shared_memory_ (file_name, len, flags, mode,
+ prot, share, addr, pos)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM");
+}
+
+// The "do-nothing" constructor.
+
+ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM");
+}
diff --git a/ace/Memory/Shared_Memory_MM.h b/ace/Memory/Shared_Memory_MM.h
new file mode 100644
index 00000000000..1ea201be975
--- /dev/null
+++ b/ace/Memory/Shared_Memory_MM.h
@@ -0,0 +1,116 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Shared_Memory_MM.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SHARED_MALLOC_MM_H
+#define ACE_SHARED_MALLOC_MM_H
+#include "ace/pre.h"
+
+#include "ace/Shared_Memory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Mem_Map.h"
+
+/**
+ * @class ACE_Shared_Memory_MM
+ *
+ * @brief Shared memory wrapper based on MMAP.
+ *
+ * This class provides a very simple-minded shared memory
+ * manager. For more a powerful memory allocator please see
+ * <ACE_Malloc>.
+ */
+class ACE_Export ACE_Shared_Memory_MM : public ACE_Shared_Memory
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_Shared_Memory_MM (void);
+
+ /// Constructor.
+ ACE_Shared_Memory_MM (ACE_HANDLE handle,
+ int length = -1,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ char *addr = 0,
+ off_t pos = 0);
+
+ /// Constructor.
+ ACE_Shared_Memory_MM (const ACE_TCHAR *file_name,
+ int len = -1,
+ int flags = O_RDWR | O_CREAT,
+ int mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_SHARED,
+ char *addr = 0, off_t pos = 0);
+
+ /// Open method.
+ int open (ACE_HANDLE handle,
+ int length = -1,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_PRIVATE,
+ char *addr = 0,
+ off_t pos = 0);
+
+ /// Open method.
+ int open (const ACE_TCHAR *file_name,
+ int len = -1,
+ int flags = O_RDWR | O_CREAT,
+ int mode = ACE_DEFAULT_FILE_PERMS,
+ int prot = PROT_RDWR,
+ int share = ACE_MAP_SHARED,
+ char *addr = 0,
+ off_t pos = 0);
+
+ /// Return the name of file that is mapped (if any).
+ const ACE_TCHAR *filename (void) const;
+
+ /// Close down the shared memory segment.
+ virtual int close (void);
+
+ /// Remove the shared memory segment and the underlying file.
+ virtual int remove (void);
+
+ // = Allocation and deallocation methods.
+ /// Create a new chuck of memory containing <size> bytes.
+ virtual void *malloc (size_t size = 0);
+
+ /// Free a chuck of memory allocated by
+ /// <ACE_Shared_Memory_MM::malloc>.
+ virtual int free (void *p);
+
+ /// Return the size of the shared memory segment.
+ virtual int get_segment_size (void) const;
+
+ /// Return the ID of the shared memory segment (i.e., an ACE_HANDLE).
+ virtual ACE_HANDLE get_id (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// This version is implemented with memory-mapped files.
+ ACE_Mem_Map shared_memory_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_MM.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SHARED_MALLOC_MM_H */
diff --git a/ace/Memory/Shared_Memory_MM.i b/ace/Memory/Shared_Memory_MM.i
new file mode 100644
index 00000000000..6a92d7677c8
--- /dev/null
+++ b/ace/Memory/Shared_Memory_MM.i
@@ -0,0 +1,89 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Shared_Memory_MM.i
+
+// Return the name of file that is mapped (if any).
+
+ACE_INLINE const ACE_TCHAR *
+ACE_Shared_Memory_MM::filename (void) const
+{
+ return this->shared_memory_.filename ();
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::open (ACE_HANDLE handle,
+ int length,
+ int prot,
+ int share,
+ char *addr,
+ off_t pos)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::open");
+ return shared_memory_.map (handle, length, prot, share, addr, pos);
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::open (const ACE_TCHAR *file_name,
+ int len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ char *addr,
+ off_t pos)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::open");
+ return shared_memory_.map (file_name, len, flags, mode,
+ prot, share, addr, pos);
+}
+
+// The overall size of the segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::get_segment_size (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::get_segment_size");
+ return this->shared_memory_.size ();
+}
+
+// Unmaps the shared memory segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::remove (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::remove");
+ return shared_memory_.remove ();
+}
+
+// Closes (unmaps) the shared memory segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::close (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::close");
+ return shared_memory_.unmap ();
+}
+
+ACE_INLINE void *
+ACE_Shared_Memory_MM::malloc (size_t)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::malloc");
+ void *addr;
+
+ return this->shared_memory_ (addr) == -1 ? 0 : addr;
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Shared_Memory_MM::get_id (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::get_id");
+ return this->shared_memory_.handle ();
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_MM::free (void *p)
+{
+ ACE_TRACE ("ACE_Shared_Memory_MM::free");
+ return p != 0;
+}
diff --git a/ace/Memory/Shared_Memory_SV.cpp b/ace/Memory/Shared_Memory_SV.cpp
new file mode 100644
index 00000000000..bd8dba00a8a
--- /dev/null
+++ b/ace/Memory/Shared_Memory_SV.cpp
@@ -0,0 +1,30 @@
+// Shared_Memory_SV.cpp
+// $Id$
+
+#include "ace/Shared_Memory_SV.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_SV.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, Shared_Memory_SV, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_SV)
+
+void
+ACE_Shared_Memory_SV::dump (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::dump");
+}
+
+ACE_Shared_Memory_SV::ACE_Shared_Memory_SV (key_t id,
+ int length,
+ int create,
+ int perms,
+ void *addr,
+ int flags)
+ : shared_memory_ (id, length, create, perms, addr, flags)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::ACE_Shared_Memory_SV");
+}
+
diff --git a/ace/Memory/Shared_Memory_SV.h b/ace/Memory/Shared_Memory_SV.h
new file mode 100644
index 00000000000..6ed7315c168
--- /dev/null
+++ b/ace/Memory/Shared_Memory_SV.h
@@ -0,0 +1,97 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Shared_Memory_SV.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SHARED_MALLOC_SV_H
+#define ACE_SHARED_MALLOC_SV_H
+#include "ace/pre.h"
+
+#include "ace/Shared_Memory.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SV_Shared_Memory.h"
+
+/**
+ * @class ACE_Shared_Memory_SV
+ *
+ * @brief Shared memory wrapper based on System V shared memory.
+ *
+ * This class provides a very simple-minded shared memory
+ * manager. For more a powerful memory allocator please see
+ * <ACE_Malloc>.
+ */
+class ACE_Export ACE_Shared_Memory_SV : public ACE_Shared_Memory
+{
+public:
+ enum
+ {
+ ACE_CREATE = IPC_CREAT,
+ ACE_OPEN = 0
+ };
+
+ // = Initialization and termination methods.
+ ACE_Shared_Memory_SV (void);
+ ACE_Shared_Memory_SV (key_t id,
+ int length,
+ int create = ACE_Shared_Memory_SV::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ void *addr = 0,
+ int flags = 0);
+
+ int open (key_t id,
+ int length,
+ int create = ACE_Shared_Memory_SV::ACE_OPEN,
+ int perms = ACE_DEFAULT_FILE_PERMS,
+ void *addr = 0,
+ int flags = 0);
+
+ /// Close down the shared memory segment.
+ virtual int close (void);
+
+ /// Remove the underlying shared memory segment.
+ virtual int remove (void);
+
+ // = Allocation and deallocation methods.
+ /// Create a new chuck of memory containing <size> bytes.
+ virtual void *malloc (size_t = 0);
+
+ /// Free a chuck of memory allocated by <ACE_Shared_Memory_SV::malloc>.
+ virtual int free (void *p);
+
+ /// Return the size of the shared memory segment.
+ virtual int get_segment_size (void) const;
+
+ /// Return the ID of the shared memory segment (i.e., a System V
+ /// shared memory internal id).
+ virtual ACE_HANDLE get_id (void) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// This version is implemented with System V shared memory
+ /// segments.
+ ACE_SV_Shared_Memory shared_memory_;
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Shared_Memory_SV.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_SHARED_MALLOC_SV_H */
diff --git a/ace/Memory/Shared_Memory_SV.i b/ace/Memory/Shared_Memory_SV.i
new file mode 100644
index 00000000000..400d9e63201
--- /dev/null
+++ b/ace/Memory/Shared_Memory_SV.i
@@ -0,0 +1,73 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Shared_Memory_SV.i
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::open (key_t id,
+ int length,
+ int create,
+ int perms,
+ void *addr,
+ int flags)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::open");
+ return shared_memory_.open_and_attach (id, length, create,
+ perms, addr, flags);
+}
+
+// The overall size of the segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::get_segment_size (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::get_segment_size");
+ return this->shared_memory_.get_segment_size ();
+}
+
+// Removes the shared memory segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::remove (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::remove");
+ return shared_memory_.remove ();
+}
+
+// Closes (detaches) the shared memory segment.
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::close (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::close");
+ return shared_memory_.detach ();
+}
+
+ACE_INLINE void *
+ACE_Shared_Memory_SV::malloc (size_t)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::malloc");
+ return this->shared_memory_.get_segment_ptr ();
+}
+
+ACE_INLINE ACE_HANDLE
+ACE_Shared_Memory_SV::get_id (void) const
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::get_id");
+ return this->shared_memory_.get_id ();
+}
+
+// The "do-nothing" constructor.
+
+ACE_INLINE
+ACE_Shared_Memory_SV::ACE_Shared_Memory_SV (void)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::ACE_Shared_Memory_SV");
+}
+
+ACE_INLINE int
+ACE_Shared_Memory_SV::free (void *p)
+{
+ ACE_TRACE ("ACE_Shared_Memory_SV::free");
+ return p != 0;
+}
diff --git a/ace/Other/Local_Name_Space.cpp b/ace/Other/Local_Name_Space.cpp
new file mode 100644
index 00000000000..ae892b07f5b
--- /dev/null
+++ b/ace/Other/Local_Name_Space.cpp
@@ -0,0 +1,225 @@
+// Local_Name_Space.cpp
+// $Id$
+
+#if !defined (ACE_LOCAL_NAME_SPACE_C)
+#define ACE_LOCAL_NAME_SPACE_C
+
+#include "ace/ACE.h"
+#include "ace/Local_Name_Space.h"
+#include "ace/RW_Process_Mutex.h"
+
+ACE_RCSID(ace, Local_Name_Space, "$Id$")
+
+ACE_NS_String::~ACE_NS_String (void)
+{
+ if (this->delete_rep_)
+ delete [] this->rep_;
+}
+
+ACE_USHORT16 *
+ACE_NS_String::fast_rep (void) const
+{
+ ACE_TRACE ("ACE_NS_String::fast_rep");
+ return this->rep_;
+}
+
+ACE_NS_String::operator ACE_NS_WString () const
+{
+ ACE_TRACE ("ACE_NS_String::operator ACE_NS_WString");
+ return ACE_NS_WString (this->rep_,
+ (this->len_ / sizeof (ACE_USHORT16)) - 1);
+}
+
+size_t
+ACE_NS_String::len (void) const
+{
+ ACE_TRACE ("ACE_NS_String::len");
+ return this->len_;
+}
+
+char *
+ACE_NS_String::char_rep (void) const
+{
+ ACE_TRACE ("ACE_NS_String::char_rep");
+ ACE_NS_WString w_string (this->rep_,
+ (this->len_ / sizeof (ACE_USHORT16)) - 1);
+ return w_string.char_rep ();
+}
+
+ACE_NS_String::ACE_NS_String (void)
+ : len_ (0),
+ rep_ (0),
+ delete_rep_ (0)
+{
+ ACE_TRACE ("ACE_NS_String::ACE_NS_String");
+}
+
+ACE_NS_String::ACE_NS_String (const ACE_NS_WString &s)
+ : len_ ((s.length () + 1) * sizeof (ACE_USHORT16)),
+ rep_ (s.ushort_rep ()),
+ delete_rep_ (1)
+{
+ ACE_TRACE ("ACE_NS_String::ACE_NS_String");
+}
+
+int
+ACE_NS_String::strstr (const ACE_NS_String &s) const
+{
+ ACE_TRACE ("ACE_NS_String::strstr");
+
+ if (this->len_ < s.len_)
+ // If they're larger than we are they can't be a substring of us!
+ return -1;
+ else if (this->len_ == s.len_)
+ // Check if we're equal.
+ return *this == s ? 0 : -1;
+ else
+ {
+ // They're smaller than we are...
+ size_t len = (this->len_ - s.len_) / sizeof (ACE_USHORT16);
+ size_t pat_len = s.len_ / sizeof (ACE_USHORT16) - 1;
+
+ for (size_t i = 0; i <= len; i++)
+ {
+ size_t j;
+
+ for (j = 0; j < pat_len; j++)
+ if (this->rep_[i + j] != s.rep_[j])
+ break;
+
+ if (j == pat_len)
+ // Found a match! Return the index.
+ return i;
+ }
+
+ return -1;
+ }
+}
+
+int
+ACE_NS_String::operator == (const ACE_NS_String &s) const
+{
+ ACE_TRACE ("ACE_NS_String::operator ==");
+ return this->len_ == s.len_
+ && ACE_OS::memcmp ((void *) this->rep_,
+ (void *) s.rep_, this->len_) == 0;
+}
+
+int
+ACE_NS_String::operator != (const ACE_NS_String &s) const
+{
+ ACE_TRACE ("ACE_NS_String::operator !=");
+ return !this->operator == (s);
+}
+
+ACE_NS_String::ACE_NS_String (ACE_USHORT16 *dst,
+ const ACE_USHORT16 *src,
+ size_t bytes)
+ : len_ (bytes),
+ rep_ (dst),
+ delete_rep_ (0)
+{
+ ACE_TRACE ("ACE_NS_String::ACE_NS_String");
+ ACE_OS::memcpy (this->rep_, src, bytes);
+}
+
+size_t
+ACE_NS_String::hash (void) const
+{
+ return ACE::hash_pjw
+ (ACE_reinterpret_cast (char *, ACE_const_cast (ACE_USHORT16 *,
+ this->rep_)),
+ this->len_);
+}
+
+ACE_NS_Internal::ACE_NS_Internal (void)
+{
+}
+
+ACE_NS_Internal::ACE_NS_Internal (ACE_NS_String &value, const char *type)
+ : value_ (value),
+ type_ (type)
+{
+ ACE_TRACE ("ACE_NS_Internal::ACE_NS_Internal");
+}
+
+int
+ACE_NS_Internal::operator == (const ACE_NS_Internal &s) const
+{
+ ACE_TRACE ("ACE_NS_Internal::operator ==");
+ return this->value_ == s.value_;
+}
+
+ACE_NS_String
+ACE_NS_Internal::value (void)
+{
+ ACE_TRACE ("ACE_NS_Internal::value");
+ return this->value_;
+}
+
+const char *
+ACE_NS_Internal::type (void)
+{
+ ACE_TRACE ("ACE_NS_Internal::type");
+ return this->type_;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+#if (1)
+template class ACE_Hash_Map_Entry<ACE_NS_String, ACE_NS_Internal>;
+template class ACE_Hash<ACE_NS_String>;
+template class ACE_Equal_To<ACE_NS_String>;
+template class ACE_Hash_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Reverse_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Manager_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>;
+#else
+template class ACE_Map_Entry<ACE_NS_String, ACE_NS_Internal>;
+template class ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Map_Reverse_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+template class ACE_Map_Iterator_Base<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>;
+#endif
+template class ACE_Unbounded_Set<ACE_Name_Binding>;
+template class ACE_Unbounded_Set_Iterator<ACE_Name_Binding>;
+template class ACE_Unbounded_Set<ACE_NS_WString>;
+template class ACE_Unbounded_Set_Iterator<ACE_NS_WString>;
+template class ACE_Node<ACE_NS_WString>;
+template class ACE_Node<ACE_Name_Binding>;
+template class ACE_Guard<ACE_RW_Process_Mutex>;
+template class ACE_Read_Guard<ACE_RW_Process_Mutex>;
+template class ACE_Write_Guard<ACE_RW_Process_Mutex>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#if (1)
+#pragma instantiate ACE_Hash_Map_Entry<ACE_NS_String, ACE_NS_Internal>
+#pragma instantiate ACE_Hash<ACE_NS_String>
+#pragma instantiate ACE_Equal_To<ACE_NS_String>
+#pragma instantiate ACE_Hash_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Reverse_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<ACE_NS_String, ACE_NS_Internal, ACE_Hash<ACE_NS_String>, ACE_Equal_To<ACE_NS_String>, ACE_Null_Mutex>
+#else
+#pragma instantiate ACE_Map_Entry<ACE_NS_String, ACE_NS_Internal>
+#pragma instantiate ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Reverse_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#pragma instantiate ACE_Map_Iterator_Base<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>
+#endif
+#pragma instantiate ACE_Unbounded_Set<ACE_Name_Binding>
+#pragma instantiate ACE_Unbounded_Set_Iterator<ACE_Name_Binding>
+#pragma instantiate ACE_Unbounded_Set<ACE_NS_WString>
+#pragma instantiate ACE_Unbounded_Set_Iterator<ACE_NS_WString>
+#pragma instantiate ACE_Node<ACE_NS_WString>
+#pragma instantiate ACE_Node<ACE_Name_Binding>
+#pragma instantiate ACE_Guard<ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Read_Guard<ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Write_Guard<ACE_RW_Process_Mutex>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+#endif /* ACE_LOCAL_NAME_SPACE_C */
diff --git a/ace/Other/Local_Name_Space.h b/ace/Other/Local_Name_Space.h
new file mode 100644
index 00000000000..9391cae4053
--- /dev/null
+++ b/ace/Other/Local_Name_Space.h
@@ -0,0 +1,130 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Local_Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain (pjain@cs.wustl.edu)
+ * @author Irfan Pyarali (irfan@wuerl.wustl.edu)
+ * @author and Douglas C. Schmidt (schmidt@cs.wustl.edu).
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_NAME_SPACE_H
+#define ACE_LOCAL_NAME_SPACE_H
+#include "ace/pre.h"
+
+#include "ace/SString.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Malloc_T.h"
+#include "ace/Synch.h"
+
+/**
+ * @class ACE_NS_String
+ *
+ * @brief This class and ACE_NS_Internal are used as Adapters to work
+ * with the Map_Manager.
+ *
+ * In order to work correctly, this class must be able to
+ * convert back and forth with <ACE_NS_WStrings>. Note that this
+ * class must not have a destructor since otherwise we'll have
+ * problems...
+ */
+class ACE_Export ACE_NS_String
+{
+public:
+ // = Initialization.
+ /// Default "no-op" constructor.
+ ACE_NS_String (void);
+
+ /// Initialization method.
+ ACE_NS_String (ACE_USHORT16 *dst,
+ const ACE_USHORT16 *src,
+ size_t len);
+
+ /// Converts an ACE_NS_WString to an ACE_NS_String;
+ ACE_NS_String (const ACE_NS_WString &);
+
+ /// Destructor
+ ~ACE_NS_String (void);
+
+ /// Converts an ACE_NS_String to fresh copy of an ACE_NS_WString;
+ operator ACE_NS_WString () const;
+
+ /// Return the ASCII character representation.
+ char *char_rep (void) const;
+
+ /// Matches on substrings.
+ int strstr (const ACE_NS_String &) const;
+
+ /// Compare an ACE_NS_String.
+ int operator == (const ACE_NS_String &) const;
+
+ /// Compare an ACE_NS_String.
+ int operator != (const ACE_NS_String &) const;
+
+ /// Returns length of the string
+ size_t len (void) const;
+
+ /// Returns the underlying representation.
+ ACE_USHORT16 *fast_rep (void) const;
+
+ /// Returns a hash value for this string.
+ size_t hash (void) const;
+
+private:
+ /// Length of the string.
+ size_t len_;
+
+ /// This actually points into shared/persistent memory.
+ ACE_USHORT16 *rep_;
+
+ /// Should rep_ be deleted when destructed (only used
+ /// for WString conversions)
+ int delete_rep_;
+};
+
+/**
+ * @class ACE_NS_Internal
+ *
+ * @brief This class and ACE_NS_String are used as Adapters to work
+ * with the Map_Manager.
+ */
+class ACE_Export ACE_NS_Internal
+{
+public:
+ /// No-op constructor.
+ ACE_NS_Internal (void);
+
+ /// Constructor.
+ ACE_NS_Internal (ACE_NS_String &value, const char *type);
+
+ /// Compare an ACE_NS_Internal
+ int operator == (const ACE_NS_Internal &) const;
+
+ /// Return value.
+ ACE_NS_String value (void);
+
+ /// Return type.
+ const char *type (void);
+
+private:
+ /// Contains the value of the string.
+ ACE_NS_String value_;
+
+ /// Contains the type of the string.
+ const char *type_;
+};
+
+// Include the ACE_Local_Name_Space templates stuff at this point.
+#include "ace/Local_Name_Space_T.h"
+
+#include "ace/post.h"
+#endif /* ACE_LOCAL_NAME_SPACE_H */
diff --git a/ace/Other/Local_Name_Space_T.cpp b/ace/Other/Local_Name_Space_T.cpp
new file mode 100644
index 00000000000..8681c76f14f
--- /dev/null
+++ b/ace/Other/Local_Name_Space_T.cpp
@@ -0,0 +1,926 @@
+// $Id$
+
+#ifndef ACE_LOCAL_NAME_SPACE_T_C
+#define ACE_LOCAL_NAME_SPACE_T_C
+
+#include "ace/ACE.h"
+#include "ace/Auto_Ptr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Local_Name_Space.h"
+
+ACE_RCSID(ace, Local_Name_Space_T, "$Id$")
+
+template <class ALLOCATOR>
+ACE_Name_Space_Map<ALLOCATOR>::ACE_Name_Space_Map (ALLOCATOR *alloc)
+ : MAP_MANAGER (alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::ACE_Name_Space_Map");
+}
+
+template <class ALLOCATOR> int
+ACE_Name_Space_Map<ALLOCATOR>::close (ALLOCATOR *alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::close");
+
+ this->allocator_ = alloc;
+ return this->close_i ();
+}
+
+template <class ALLOCATOR> int
+ACE_Name_Space_Map<ALLOCATOR>::bind (const ACE_NS_String &ext_id,
+ const ACE_NS_Internal &int_id,
+ ALLOCATOR *alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::bind");
+
+ this->allocator_ = alloc;
+ return this->bind_i (ext_id, int_id);
+}
+
+template <class ALLOCATOR> int
+ACE_Name_Space_Map<ALLOCATOR>::unbind (const ACE_NS_String &ext_id,
+ ACE_NS_Internal &int_id,
+ ALLOCATOR *alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::unbind");
+
+ this->allocator_ = alloc;
+ return this->unbind_i (ext_id, int_id);
+}
+
+template <class ALLOCATOR> int
+ACE_Name_Space_Map<ALLOCATOR>::rebind (const ACE_NS_String &ext_id,
+ const ACE_NS_Internal &int_id,
+ ACE_NS_String &old_ext_id,
+ ACE_NS_Internal &old_int_id,
+ ALLOCATOR *alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::rebind");
+
+ this->allocator_ = alloc;
+ return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id);
+}
+
+template <class ALLOCATOR> int
+ACE_Name_Space_Map<ALLOCATOR>::find (const ACE_NS_String &ext_id,
+ ACE_NS_Internal &int_id,
+ ALLOCATOR *alloc)
+{
+ ACE_TRACE ("ACE_Name_Space_Map::find");
+
+ this->allocator_ = alloc;
+ return this->find_i (ext_id, int_id);
+}
+
+#if defined (ACE_WIN32)
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::remap (EXCEPTION_POINTERS *ep)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::remap");
+
+ void *addr = (void *) ep->ExceptionRecord->ExceptionInformation[1];
+
+ // The following requires Memory Pool to have ::remap()
+ // defined. Thus currently this will only work for
+ // ACE_MMap_Memory_Pool.
+ if (this->allocator_->alloc ().memory_pool ().remap (addr) == -1)
+ // Kick it upstairs...
+ return EXCEPTION_CONTINUE_SEARCH;
+
+#if __X86__
+ // This is 80x86-specific.
+ ep->ContextRecord->Edi = (DWORD) addr;
+#elif __MIPS__
+ ep->ContextRecord->IntA0 =
+ ep->ContextRecord->IntV0 = (DWORD) addr;
+ ep->ContextRecord->IntT5 = ep->ContextRecord->IntA0 + 3;
+#endif /* __X86__ */
+ // Resume execution at the original point of "failure."
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+#endif /* ACE_WIN32 */
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::shared_bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type,
+ int rebind)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->shared_bind_i (name, value, type, rebind);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::shared_bind_i (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type,
+ int rebind)
+{
+
+ ACE_TRACE ("ACE_Local_Name_Space::shared_bind_i");
+ size_t name_len = (name.length () + 1) * sizeof (ACE_USHORT16);
+ size_t value_len = (value.length () + 1) * sizeof (ACE_USHORT16);
+ size_t type_len = ACE_OS::strlen (type) + 1;
+ size_t total_len = name_len + value_len + type_len;
+ char *ptr = (char *) this->allocator_->malloc (total_len);
+
+ if (ptr == 0)
+ return -1;
+ else
+ {
+ // Note that the value_rep *must* come first to make sure we can
+ // retrieve this pointer later on in unbind().
+ ACE_USHORT16 *value_rep = (ACE_USHORT16 *) (ptr);
+ ACE_USHORT16 *name_rep = (ACE_USHORT16 *) (ptr + value_len);
+ char *new_type = (char *) (ptr + value_len + name_len);
+
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> name_urep (name.ushort_rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> value_urep (value.ushort_rep ());
+ ACE_NS_String new_name (name_rep, name_urep.get (), name_len);
+ ACE_NS_String new_value (value_rep, value_urep.get (), value_len);
+
+ ACE_OS::strcpy (new_type, type);
+ ACE_NS_Internal new_internal (new_value, new_type);
+ int result = -1;
+
+ if (rebind == 0)
+ {
+ // Do a normal bind. This will fail if there's already an
+ // <new_internal> with the same name.
+ result = this->name_space_map_->bind (new_name, new_internal, this->allocator_);
+
+ if (result == 1)
+ {
+ // Entry already existed so bind failed. Free our dynamically allocated memory.
+ this->allocator_->free ((void *) ptr);
+ return result;
+ }
+ }
+ else
+ {
+ // Do a rebind. If there's already any entry, this will return the existing
+ // <new_name> and <new_internal> and overwrite the existing name binding.
+ ACE_NS_String old_name;
+ ACE_NS_Internal old_internal;
+
+ result = this->name_space_map_->rebind (new_name, new_internal,
+ old_name, old_internal,
+ this->allocator_);
+ if (result == 1)
+ {
+ // Free up the memory we allocated in shared_bind(). Note that this
+ // assumes that the "value" pointer comes first and that the value,
+ // name, and type are contiguously allocated (see above for details)
+ this->allocator_->free ((void *) (old_internal.value ()).fast_rep ());
+ }
+ }
+
+ if (result == -1)
+ // Free our dynamically allocated memory.
+ this->allocator_->free ((void *) ptr);
+ else
+ // If bind() or rebind() succeed, they will automatically sync
+ // up the map manager entry. However, we must sync up our
+ // name/value memory.
+ this->allocator_->sync (ptr, total_len);
+
+ return result;
+ }
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::unbind (const ACE_NS_WString &name)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->unbind_i (name);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::unbind_i (const ACE_NS_WString &name)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::unbind_i");
+
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+ ACE_NS_String ns_name (name);
+ ACE_NS_Internal ns_internal;
+ if (this->name_space_map_->unbind (ns_name,
+ ns_internal,
+ this->allocator_) != 0)
+ return -1;
+
+ // Free up the memory we allocated in shared_bind(). Note that this
+ // assumes that the "value" pointer comes first and that the value,
+ // name and type are contiguously allocated (see shared_bind() for
+ // details)
+ this->allocator_->free ((void *) (ns_internal.value ()).fast_rep ());
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::bind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ return this->shared_bind (name, value, type, 0);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::rebind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::rebind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ return this->shared_bind (name, value, type, 1);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::resolve (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->resolve_i (name, value, type);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::resolve_i (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::resolve_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ ACE_NS_String ns_name (name);
+ ACE_NS_Internal ns_internal;
+ ACE_NS_String nbc_string; // Note the classy variable name! :)
+
+ if (this->name_space_map_->find (ns_name,
+ ns_internal,
+ this->allocator_) != 0)
+ return -1;
+
+ // Calls conversion operator and then calls the ACE_NS_WString
+ // assignment operator to get a fresh copy. (*#*(@#&!*@!!*@&( HP
+ // compiler causes us to add an extra copy explicitly !! :)
+ nbc_string = ns_internal.value ();
+ value = nbc_string;
+
+ // Gets type and then the actual reprsentation which is a
+ // ACE_USHORT16
+ const char *temp = ns_internal.type ();
+
+ size_t len = ACE_OS::strlen (ns_internal.type ());
+ // Makes a copy here. Caller needs to call delete to free up
+ // memory.
+ char *new_type;
+ ACE_NEW_RETURN (new_type,
+ char [len + 1],
+ -1);
+
+ ACE_OS::strsncpy (new_type, temp, len + 1);
+ type = new_type;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::open (ACE_Naming_Context::Context_Scope_Type scope_in)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::open");
+ this->ns_scope_ = scope_in;
+
+ return this->create_manager ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Local_Name_Space (void)
+ : allocator_ (0),
+ name_space_map_ (0),
+ name_options_ (0)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::ACE_Local_Name_Space");
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::ACE_Local_Name_Space (ACE_Naming_Context::Context_Scope_Type scope_in,
+ ACE_Name_Options *name_options)
+ : name_options_ (name_options)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::ACE_Local_Name_Space");
+ if (this->open (scope_in) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_Local_Name_Space::ACE_Local_Name_Space")));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::~ACE_Local_Name_Space (void)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::~ACE_Local_Name_Space");
+
+ // Remove the map.
+ delete this->allocator_;
+ delete this->lock_;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::create_manager (void)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->create_manager_i ();
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::create_manager_i (void)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::create_manager_i");
+ // Get directory name
+ const ACE_TCHAR *dir = this->name_options_->namespace_dir ();
+ const ACE_TCHAR *database = this->name_options_->database ();
+
+ // Use process name as the file name.
+ size_t len = ACE_OS::strlen (dir);
+ len += ACE_OS::strlen (ACE_DIRECTORY_SEPARATOR_STR);
+ len += ACE_OS::strlen (database) + 1;
+
+ if (len >= MAXNAMELEN + MAXPATHLEN)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ ACE_OS::strcpy (this->context_file_, dir);
+ ACE_OS::strcat (this->context_file_, ACE_DIRECTORY_SEPARATOR_STR);
+ ACE_OS::strcat (this->context_file_, database);
+
+#if !defined (CHORUS)
+ ACE_MEM_POOL_OPTIONS options (this->name_options_->base_address ());
+#else
+ // Use base address == 0, don't use a fixed address.
+ ACE_MEM_POOL_OPTIONS options (0,
+ 0,
+ 0,
+ ACE_CHORUS_LOCAL_NAME_SPACE_T_SIZE);
+#endif /* CHORUS */
+
+ ACE_TCHAR lock_name_for_local_name_space [MAXNAMELEN + MAXPATHLEN];
+ ACE_TCHAR lock_name_for_backing_store [MAXPATHLEN + MAXNAMELEN];
+ const ACE_TCHAR *postfix = database;
+
+ size_t length = 0;
+ length = sizeof lock_name_for_local_name_space / sizeof (ACE_TCHAR);
+ ACE_OS::strsncpy (lock_name_for_local_name_space,
+ dir,
+ length);
+
+ ACE_OS::strncat (lock_name_for_local_name_space,
+ ACE_DIRECTORY_SEPARATOR_STR,
+ length - ACE_OS::strlen (lock_name_for_local_name_space));
+ ACE_OS::strncat (lock_name_for_local_name_space,
+ ACE_LIB_TEXT ("name_space_"),
+ length - ACE_OS::strlen (lock_name_for_local_name_space));
+ ACE_OS::strncat (lock_name_for_local_name_space,
+ postfix,
+ length - ACE_OS::strlen (lock_name_for_local_name_space));
+
+ length = sizeof lock_name_for_backing_store / sizeof (ACE_TCHAR);
+ ACE_OS::strsncpy (lock_name_for_backing_store,
+ dir,
+ length);
+ ACE_OS::strncat (lock_name_for_backing_store,
+ ACE_DIRECTORY_SEPARATOR_STR,
+ length - ACE_OS::strlen (lock_name_for_backing_store));
+ ACE_OS::strncat (lock_name_for_backing_store,
+ ACE_LIB_TEXT ("backing_store_"),
+ length - ACE_OS::strlen (lock_name_for_backing_store));
+ ACE_OS::strncat (lock_name_for_backing_store,
+ postfix,
+ length - ACE_OS::strlen (ACE_LIB_TEXT ("backing_store_")));
+
+ // Create the allocator with the appropriate options.
+ ACE_NEW_RETURN (this->allocator_,
+ ALLOCATOR (this->context_file_,
+ lock_name_for_backing_store,
+ &options), -1);
+
+ if (ACE_LOG_MSG->op_status ())
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Allocator::Allocator\n")),
+ -1);
+
+ ACE_NEW_RETURN (this->lock_,
+ ACE_LOCK (lock_name_for_local_name_space),
+ -1);
+
+#if !defined (ACE_LACKS_ACCESS)
+ // Now check if the backing store has been created successfully
+ if (ACE_OS::access (this->context_file_, F_OK) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("create_manager\n")),
+ -1);
+#endif /* ACE_LACKS_ACCESS */
+
+ void *ns_map = 0;
+
+ // This is the easy case since if we find the Name Server Map
+ // Manager we know it's already initialized.
+ if (this->allocator_->find (ACE_NAME_SERVER_MAP, ns_map) == 0)
+ {
+ this->name_space_map_ = (ACE_Name_Space_Map <ALLOCATOR> *) ns_map;
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("name_space_map_ = %d, ns_map = %d\n"),
+ this->name_space_map_, ns_map));
+ }
+
+ // This is the hard part since we have to avoid potential race
+ // conditions... We will use the double check here
+ else
+ {
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ // This is the easy case since if we find the Name Server Map
+ // Manager we know it's already initialized.
+ if (this->allocator_->find (ACE_NAME_SERVER_MAP, ns_map) == 0)
+ {
+ this->name_space_map_ = (ACE_Name_Space_Map <ALLOCATOR> *) ns_map;
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("name_space_map_ = %d, ns_map = %d\n"),
+ this->name_space_map_, ns_map));
+ }
+ else
+ {
+ size_t map_size = sizeof *this->name_space_map_;
+ ns_map = this->allocator_->malloc (map_size);
+
+ // Initialize the map into its memory location (e.g., shared memory).
+ this->name_space_map_ =
+ new (ns_map) ACE_Name_Space_Map <ALLOCATOR> (this->allocator_);
+
+ if (this->allocator_->bind (ACE_NAME_SERVER_MAP, ns_map) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("create_manager\n")), -1);
+ }
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("name_space_map_ = %d, ns_map = %d\n"),
+ this->name_space_map_, ns_map));
+ }
+
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_names_i (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_names_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ int result = 1;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance())
+ {
+ if (map_entry->ext_id_.strstr (pattern) != -1)
+ {
+ ACE_NS_WString entry (map_entry->ext_id_ );
+
+ if (set.insert (entry) == -1)
+ {
+ result = -1;
+ break;
+ }
+ else
+ result = 0;
+ }
+ }
+
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_values_i (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_values_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ int result = 1;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance ())
+ {
+ if (map_entry->int_id_.value ().strstr (pattern) != -1)
+ {
+ ACE_NS_WString entry (map_entry->int_id_.value ());
+
+ if (set.insert (entry) == -1)
+ {
+ result = -1;
+ break;
+ }
+ else
+ result = 0;
+ }
+ }
+
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_types_i (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_types_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ char *compiled_regexp = 0;
+
+ // Note that char_rep() allocates memory so we need to delete it
+ char *pattern_rep = pattern.char_rep ();
+
+ // Check for wildcard case first.
+ if (ACE_OS::strcmp ("", pattern_rep) == 0)
+ ACE_ALLOCATOR_RETURN (compiled_regexp,
+ ACE_OS::strdup (""),
+ -1);
+ else
+ // Compile the regular expression (the 0's cause ACE_OS::compile
+ // to allocate space).
+#if defined (ACE_HAS_REGEX)
+ compiled_regexp = ACE_OS::compile (pattern_rep, 0, 0);
+#else
+ // If we don't have regular expressions just use the pattern
+ // directly.
+ compiled_regexp = pattern_rep;
+#endif /* ACE_HAS_REGEX */
+
+ int result = 1;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance ())
+ {
+ // Get the type
+ const char *type = map_entry->int_id_.type ();
+
+ // Everything matches the wildcard.
+ if (ACE_OS::strcmp ("", pattern_rep) == 0
+#if defined (ACE_HAS_REGEX)
+ || ACE_OS::step (type, compiled_regexp) != 0)
+#else
+ // If we don't have regular expressions just use strstr() for
+ // substring matching.
+ || ACE_OS::strstr (type, compiled_regexp) != 0)
+#endif /* ACE_HAS_REGEX */
+
+ {
+ ACE_NS_WString entry (type);
+
+ if (set.insert (entry) == -1)
+ {
+ result = -1;
+ break;
+ }
+ else
+ result = 0;
+ }
+ }
+#if defined (ACE_HAS_REGEX)
+ if (compiled_regexp)
+ ACE_OS::free ((void *) compiled_regexp);
+#endif /* ACE_HAS_REGEX */
+ delete [] pattern_rep; // delete pattern_rep;
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space <ACE_MEM_POOL_2, ACE_LOCK>::list_name_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_name_entries_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance())
+ {
+ if (map_entry->ext_id_.strstr (pattern) != -1)
+ {
+ ACE_Name_Binding entry (map_entry->ext_id_,
+ map_entry->int_id_.value (),
+ map_entry->int_id_.type ());
+
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_value_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_value_entries_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance ())
+ {
+ if (map_entry->int_id_.value ().strstr (pattern) != -1)
+ {
+ ACE_Name_Binding entry (map_entry->ext_id_,
+ map_entry->int_id_.value (),
+ map_entry->int_id_.type ());
+
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_type_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Local_Name_Space::list_type_entries_i");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ char *compiled_regexp = 0;
+ // Note that char_rep() allocates memory so we need to delete it
+ char *pattern_rep = pattern.char_rep ();
+
+ // Check for wildcard case first.
+ if (ACE_OS::strcmp ("", pattern_rep) == 0)
+ compiled_regexp = ACE_OS::strdup ("");
+ else
+ // Compile the regular expression (the 0's cause ACE_OS::compile to allocate space).
+#if defined (ACE_HAS_REGEX)
+ compiled_regexp = ACE_OS::compile (pattern_rep, 0, 0);
+#else /* If we don't have regular expressions just the pattern directly. */
+ compiled_regexp = pattern_rep;
+#endif /* ACE_HAS_REGEX */
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance ())
+ {
+ // Get the type.
+ const char *type = map_entry->int_id_.type ();
+
+ if (ACE_OS::strcmp ("", pattern_rep) == 0 // Everything matches the wildcard.
+#if defined (ACE_HAS_REGEX)
+ || ACE_OS::step (type, compiled_regexp) != 0)
+#else /* If we don't have regular expressions just use strstr() for substring matching. */
+ || ACE_OS::strstr (type, compiled_regexp) != 0)
+#endif /* ACE_HAS_REGEX */
+ {
+ ACE_Name_Binding entry (map_entry->ext_id_,
+ map_entry->int_id_.value (),
+ map_entry->int_id_.type ());
+
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+#if defined (ACE_HAS_REGEX)
+ if (compiled_regexp)
+ ACE_OS::free ((void *) compiled_regexp);
+#endif /* ACE_HAS_REGEX */
+ delete [] pattern_rep; // delete pattern_rep;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> void
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::dump_i (void) const
+{
+ ACE_TRACE ("ACE_Local_Name_Space::dump_i");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+
+ MAP_ITERATOR map_iterator (*this->name_space_map_);
+ MAP_ENTRY *map_entry;
+
+ for (map_entry = 0;
+ map_iterator.next (map_entry) != 0;
+ map_iterator.advance())
+ {
+ char *key = map_entry->ext_id_.char_rep ();
+ char *value = map_entry->int_id_.value ().char_rep ();
+#if !defined (ACE_NLOGGING)
+ const char *type = map_entry->int_id_.type ();
+#endif /* ! ACE_NLOGGING */
+
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("key=%s\nvalue=%s\ntype=%s\n"),
+ key, value, type));
+ // We need to delete key and value since char_rep allocates memory for them
+ delete [] key;
+ delete [] value;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_names (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_names_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_values (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_values_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_types (ACE_PWSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_types_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space <ACE_MEM_POOL_2, ACE_LOCK>::list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_name_entries_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_value_entries_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> int
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+ int result = 0;
+ ACE_SEH_TRY
+ {
+ result = this->list_type_entries_i (set, pattern);
+ }
+ ACE_SEH_EXCEPT (this->remap (GetExceptionInformation ()))
+ {
+ }
+ return result;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK> void
+ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK>::dump (void) const
+{
+ // Note that we *must* use structured exception handling here
+ // because (1) we may need to commit virtual memory pages and (2)
+ // C++ exception handling doesn't support resumption.
+
+ // This should really be a const cast
+ ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK> *fake_this =
+ (ACE_Local_Name_Space<ACE_MEM_POOL_2, ACE_LOCK> *) this;
+ ACE_UNUSED_ARG (fake_this);
+
+ ACE_SEH_TRY
+ {
+ this->dump_i ();
+ }
+ ACE_SEH_EXCEPT (fake_this->remap (GetExceptionInformation ()))
+ {
+ }
+}
+
+#endif /* ACE_LOCAL_NAME_SPACE_T_C */
diff --git a/ace/Other/Local_Name_Space_T.h b/ace/Other/Local_Name_Space_T.h
new file mode 100644
index 00000000000..344e8a95511
--- /dev/null
+++ b/ace/Other/Local_Name_Space_T.h
@@ -0,0 +1,266 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Local_Name_Space_T.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain <pjain@cs.wustl.edu>
+ * @author Irfan Pyarali <irfan@wuerl.wustl.edu> and
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOCAL_NAME_SPACE_T_H
+#define ACE_LOCAL_NAME_SPACE_T_H
+#include "ace/pre.h"
+
+#include "ace/Name_Space.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Naming_Context.h"
+#include "ace/SString.h"
+#include "ace/Local_Name_Space.h"
+
+// A short-hand name for our set of name/value/type tuples passed back
+// to callers.
+typedef ACE_Unbounded_Set<ACE_NS_WString> ACE_WSTRING_SET;
+
+// Simplify later usage by defining typedefs.
+#if (1)
+#include "ace/Hash_Map_Manager.h"
+typedef ACE_Hash_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_MANAGER;
+typedef ACE_Hash_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_ITERATOR;
+typedef ACE_Hash_Map_Entry <ACE_NS_String, ACE_NS_Internal> MAP_ENTRY;
+#else
+#include "ace/Map_Manager.h"
+typedef ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_MANAGER;
+typedef ACE_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_ITERATOR;
+typedef ACE_Map_Entry <ACE_NS_String, ACE_NS_Internal> MAP_ENTRY;
+#endif /* 0 */
+
+/**
+ * @class ACE_Name_Space_Map
+ *
+ * @brief This class serves as a Proxy that ensures our process always
+ * has the appropriate allocator in place for every operation
+ * that accesses or updates the Map Manager.
+ *
+ * We need this class because otherwise the ALLOCATOR
+ * pointer will be stored in the Map_Manager that resides within
+ * shared memory. Naturally, this will cause horrible problems
+ * since only the first process to set that pointer will be
+ * guaranteed the address of the ALLOCATOR is meaningful!
+ */
+template <class ALLOCATOR>
+class ACE_Name_Space_Map : public MAP_MANAGER
+{
+public:
+ /// Constructor.
+ ACE_Name_Space_Map (ALLOCATOR *alloc);
+
+ // = The following methods are Proxies to the underlying methods
+ // provided by <ACE_Hash_Map_Manager>. When they are called, they
+ // acquire the lock, set the allocator to the one specific to this
+ // process, and then call down to perform the intended operation.
+ int bind (const ACE_NS_String &,
+ const ACE_NS_Internal &,
+ ALLOCATOR *alloc);
+
+ int unbind (const ACE_NS_String &,
+ ACE_NS_Internal &,
+ ALLOCATOR *alloc);
+
+ int rebind (const ACE_NS_String &,
+ const ACE_NS_Internal &,
+ ACE_NS_String &,
+ ACE_NS_Internal &,
+ ALLOCATOR *alloc);
+
+ int find (const ACE_NS_String &,
+ ACE_NS_Internal &,
+ ALLOCATOR *alloc);
+
+ int close (ALLOCATOR *alloc);
+};
+
+/**
+ * @class ACE_Local_Name_Space
+ *
+ * @brief Maintaining accesses Local Name Server Database. Allows to
+ * add NameBindings, change them, remove them and resolve
+ * NameBindings.
+ *
+ * Manages a Naming Service for a local name space which
+ * includes bindings for node_local and host_local naming
+ * contexts. All strings are stored in wide character format.
+ * A Name Binding consists of a name (that's the key), a value
+ * string and an optional type string (no wide chars).
+ */
+template <ACE_MEM_POOL_1, class ACE_LOCK>
+class ACE_Local_Name_Space : public ACE_Name_Space
+{
+public:
+ // = Initialization and termination methods.
+ /// "Do-nothing" constructor.
+ ACE_Local_Name_Space (void);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace.
+ */
+ ACE_Local_Name_Space (ACE_Naming_Context::Context_Scope_Type scope_in,
+ ACE_Name_Options *name_options);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace.
+ */
+ int open (ACE_Naming_Context::Context_Scope_Type scope_in);
+
+ /// destructor, do some cleanup :TBD: last dtor should "compress"
+ /// file
+ ~ACE_Local_Name_Space (void);
+
+ /// Bind a new name to a naming context (Wide character strings).
+ virtual int bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type = "");
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Local_Name_Space or bind a new name to the context, if it
+ * didn't exist yet. (Wide charcter strings interface).
+ */
+ virtual int rebind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type = "");
+
+ /// Delete a name from a ACE_Local_Name_Space (Wide charcter strings
+ /// Interface).
+ virtual int unbind (const ACE_NS_WString &name);
+ virtual int unbind_i (const ACE_NS_WString &name);
+
+ /// Get value and type of a given name binding (Wide chars). The
+ /// caller is responsible for deleting <type>!
+ virtual int resolve (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type);
+ virtual int resolve_i (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type);
+
+ /// Get a set of names matching a specified pattern (wchars). Matching
+ /// means the names must begin with the pattern string.
+ virtual int list_names (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_names_i (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /// Get a set of values matching a specified pattern (wchars). Matching
+ /// means the values must begin with the pattern string.
+ virtual int list_values (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_values_i (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /// Get a set of types matching a specified pattern (wchars). Matching
+ /// means the types must begin with the pattern string.
+ virtual int list_types (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_types_i (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_name_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_value_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+ virtual int list_type_entries_i (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /// Dump the state of the object
+ virtual void dump (void) const;
+ virtual void dump_i (void) const;
+
+ // = I just know this is going to cause problems on some platform...
+ typedef ACE_Allocator_Adapter <ACE_Malloc <ACE_MEM_POOL_2, ACE_LOCK> >
+ ALLOCATOR;
+
+private:
+#if defined (ACE_WIN32)
+ /// Remap the backing store
+ int remap (EXCEPTION_POINTERS *ep);
+#endif /* ACE_WIN32 */
+
+ /// Factor out code from <bind> and <rebind>.
+ int shared_bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type, int rebind);
+ int shared_bind_i (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type, int rebind);
+
+ /// Allocate the appropriate type of map manager that stores the
+ /// key/value binding.
+ int create_manager (void);
+ int create_manager_i (void);
+
+ /// Pointer to the allocator
+ ALLOCATOR *allocator_;
+
+ /// Pointer to the allocated map manager.
+ ACE_Name_Space_Map <ALLOCATOR> *name_space_map_;
+
+ /// Scope of this naming context (e.g., PROC_LOCAL, NODE_LOCAL, or
+ /// NET_LOCAL).
+ ACE_Naming_Context::Context_Scope_Type ns_scope_;
+
+ /// Keep track of the options such as database name etc
+ ACE_Name_Options *name_options_;
+
+ /// Name of the file used as the backing store.
+ ACE_TCHAR context_file_[MAXPATHLEN + MAXNAMELEN];
+
+ /// Synchronization variable.
+ ACE_LOCK *lock_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Local_Name_Space_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Local_Name_Space_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include "ace/post.h"
+#endif /* ACE_LOCAL_NAME_SPACE_T_H */
diff --git a/ace/Other/Msg_WFMO_Reactor.cpp b/ace/Other/Msg_WFMO_Reactor.cpp
new file mode 100644
index 00000000000..ded0e200926
--- /dev/null
+++ b/ace/Other/Msg_WFMO_Reactor.cpp
@@ -0,0 +1,90 @@
+// $Id$
+
+#include "ace/Msg_WFMO_Reactor.h"
+
+ACE_RCSID(ace, Msg_WFMO_Reactor, "$Id$")
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_MSG_WFMO)
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Msg_WFMO_Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_Msg_WFMO_Reactor::ACE_Msg_WFMO_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : ACE_WFMO_Reactor (sh, tq)
+{
+}
+
+ACE_Msg_WFMO_Reactor::ACE_Msg_WFMO_Reactor (size_t size,
+ int unused,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq)
+ : ACE_WFMO_Reactor (size, unused, sh, tq)
+{
+}
+
+ACE_Msg_WFMO_Reactor::~ACE_Msg_WFMO_Reactor (void)
+{
+}
+
+int
+ACE_Msg_WFMO_Reactor::wait_for_multiple_events (int timeout,
+ int alertable)
+{
+ // Wait for any of handles_ to be active, or until timeout expires.
+ // If <alertable> is enabled allow asynchronous completion of
+ // ReadFile and WriteFile operations. QS_ALLINPUT allows
+ // <MsgWaitForMultipleObjectsEx> to wait for any message is in the
+ // queue.
+#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
+ return ::MsgWaitForMultipleObjectsEx (this->handler_rep_.max_handlep1 (),
+ this->handler_rep_.handles (),
+ timeout,
+ QS_ALLINPUT,
+ alertable);
+#else
+ ACE_UNUSED_ARG (alertable);
+ return ::MsgWaitForMultipleObjects (this->handler_rep_.max_handlep1 (),
+ this->handler_rep_.handles (),
+ FALSE,
+ timeout,
+ QS_ALLINPUT);
+#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
+}
+
+int
+ACE_Msg_WFMO_Reactor::dispatch_window_messages (void)
+{
+ int number_of_messages = 0;
+ MSG msg;
+
+ // Process all pending message from this thread's message queue
+ while (::PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ ::TranslateMessage (&msg);
+ if (msg.message == WM_QUIT)
+ {
+ // Should inform the main thread
+ ::PostQuitMessage (msg.wParam);
+ return -1;
+ }
+
+ ::DispatchMessage (&msg);
+ number_of_messages++;
+ }
+
+ return number_of_messages;
+}
+
+DWORD
+ACE_Msg_WFMO_Reactor::poll_remaining_handles (size_t slot)
+{
+ return ::MsgWaitForMultipleObjects (this->handler_rep_.max_handlep1 () - slot,
+ this->handler_rep_.handles () + slot,
+ FALSE,
+ 0,
+ QS_ALLINPUT);
+}
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
diff --git a/ace/Other/Msg_WFMO_Reactor.h b/ace/Other/Msg_WFMO_Reactor.h
new file mode 100644
index 00000000000..827a51e0e0f
--- /dev/null
+++ b/ace/Other/Msg_WFMO_Reactor.h
@@ -0,0 +1,114 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Msg_WFMO_Reactor.h
+ *
+ * $Id$
+ *
+ * @author Beskrovny Evgeny <evgeny_beskrovny@icomverse.com>
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_MSG_WFMO_REACTOR_H
+#define ACE_MSG_WFMO_REACTOR_H
+#include "ace/pre.h"
+
+#include "ace/WFMO_Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_MSG_WFMO)
+
+/**
+ * @class ACE_Msg_WFMO_Reactor
+ *
+ * @brief An OO event demultiplexor and event handler dispatcher for
+ * Win32 <MsgWaitForMultipleObjects>.
+ *
+ * The ACE_Msg_WFMO_Reactor is an OO event demultiplexor and
+ * event handler Reactor. It differs from <ACE_WFMO_Reactor> by
+ * its ability to react on Windows messages. It is needed when
+ * the task should serve also as a COM/DCOM server.
+ */
+class ACE_Export ACE_Msg_WFMO_Reactor : public ACE_WFMO_Reactor
+{
+public:
+ // = Initialization and termination methods.
+ /// Initialize <ACE_Msg_WFMO_Reactor> with the default size.
+ ACE_Msg_WFMO_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /**
+ * Initialize <ACE_Msg_WFMO_Reactor> with size <size>. Two slots will be
+ * added to the <size> parameter which will store handles used for
+ * internal management purposes.
+ */
+ ACE_Msg_WFMO_Reactor (size_t size,
+ int unused = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0);
+
+ /// Close down the ACE_Msg_WFMO_Reactor and release all of its resources.
+ virtual ~ACE_Msg_WFMO_Reactor (void);
+
+ /**
+ * This event loop driver blocks for up to <max_wait_time> before
+ * returning. It will return earlier if timer events, I/O events,
+ * window events, or signal events occur. Note that <max_wait_time>
+ * can be 0, in which case this method blocks indefinitely until
+ * events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * <MsgWaitForMultipleObjects> is used as the demultiplexing call
+ *
+ * Returns the total number of <ACE_Event_Handler>s that were
+ * dispatched, 0 if the <max_wait_time> elapsed without dispatching
+ * any handlers, or -1 if an error occurs.
+ *
+ * The only difference between <alertable_handle_events> and
+ * <handle_events> is that in the alertable case, MWMO_ALERTABLE is
+ * passed to <MsgWaitForMultipleObjects> for the <bAlertable>
+ * option.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+ virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ /**
+ * This method is just like the one above, except the
+ * <max_wait_time> value is a reference and can therefore never be
+ * NULL.
+ */
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+ virtual int alertable_handle_events (ACE_Time_Value &max_wait_time);
+
+protected:
+ /// Wait for timer and I/O events to occur.
+ virtual int wait_for_multiple_events (int timeout,
+ int alertable);
+
+ /// Check for activity on remaining handles.
+ virtual DWORD poll_remaining_handles (size_t index);
+
+ /// Dispatches window messages.
+ virtual int dispatch_window_messages (void);
+};
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
+
+#if defined (__ACE_INLINE__)
+#include "ace/Msg_WFMO_Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_MSG_WFMO_REACTOR_H */
diff --git a/ace/Other/Msg_WFMO_Reactor.i b/ace/Other/Msg_WFMO_Reactor.i
new file mode 100644
index 00000000000..c8d7f25c8d7
--- /dev/null
+++ b/ace/Other/Msg_WFMO_Reactor.i
@@ -0,0 +1,30 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if defined (ACE_WIN32) && !defined (ACE_LACKS_MSG_WFMO)
+
+ACE_INLINE int
+ACE_Msg_WFMO_Reactor::handle_events (ACE_Time_Value &how_long)
+{
+ return this->event_handling (&how_long, 0);
+}
+
+ACE_INLINE int
+ACE_Msg_WFMO_Reactor::alertable_handle_events (ACE_Time_Value &how_long)
+{
+ return this->event_handling (&how_long, MWMO_ALERTABLE);
+}
+
+ACE_INLINE int
+ACE_Msg_WFMO_Reactor::handle_events (ACE_Time_Value *how_long)
+{
+ return this->event_handling (how_long, 0);
+}
+
+ACE_INLINE int
+ACE_Msg_WFMO_Reactor::alertable_handle_events (ACE_Time_Value *how_long)
+{
+ return this->event_handling (how_long, MWMO_ALERTABLE);
+}
+
+#endif /* ACE_WIN32 && !ACE_LACKS_MSG_WFMO */
diff --git a/ace/Other/Name_Proxy.cpp b/ace/Other/Name_Proxy.cpp
new file mode 100644
index 00000000000..cccd599912c
--- /dev/null
+++ b/ace/Other/Name_Proxy.cpp
@@ -0,0 +1,201 @@
+// Name_Proxy.cpp
+// $Id$
+
+#include "ace/Name_Proxy.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Name_Proxy, "$Id$")
+
+void
+ACE_Name_Proxy::dump (void) const
+{
+ ACE_TRACE ("ACE_Name_Proxy::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->connector_.dump ();
+ this->peer_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("reactor_ = %x"), this->reactor_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Default constructor.
+
+ACE_Name_Proxy::ACE_Name_Proxy (void)
+ : reactor_ (0)
+{
+ ACE_TRACE ("ACE_Name_Proxy::ACE_Name_Proxy");
+}
+
+// Establish binding with the ACE_Name Server at remote_addr.
+
+int
+ACE_Name_Proxy::open (const ACE_INET_Addr &remote_addr,
+ ACE_Synch_Options& options)
+{
+ ACE_TRACE ("ACE_Name_Proxy::open");
+ ACE_Time_Value *timeout = 0;
+
+ if (options[ACE_Synch_Options::USE_TIMEOUT])
+ timeout = ACE_const_cast (ACE_Time_Value *, options.time_value ());
+
+ // Initiate the connection.
+ return this->connector_.connect (this->peer_,
+ remote_addr,
+ timeout);
+}
+
+// Establish binding with the ACE_Name Server at remote_addr.
+
+ACE_Name_Proxy::ACE_Name_Proxy (const ACE_INET_Addr &remote_addr,
+ ACE_Synch_Options& options)
+{
+ ACE_TRACE ("ACE_Name_Proxy::ACE_Name_Proxy");
+ if (this->open (remote_addr, options) == -1
+ && options[ACE_Synch_Options::USE_TIMEOUT] && errno != EWOULDBLOCK)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Name_Proxy::ACE_Name_Proxy")));
+}
+
+// Obtain underlying handle.
+
+/* VIRTUAL */ ACE_HANDLE
+ACE_Name_Proxy::get_handle (void) const
+{
+ ACE_TRACE ("ACE_Name_Proxy::get_handle");
+ return this->peer_.get_handle ();
+}
+
+int
+ACE_Name_Proxy::request_reply (ACE_Name_Request &request)
+{
+ ACE_TRACE ("ACE_Name_Proxy::request_reply");
+ void *buffer;
+ ssize_t length = request.encode (buffer);
+
+ if (length == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("encode failed")),
+ -1);
+
+ // Transmit request via a blocking send.
+
+ if (this->peer_.send_n (buffer, length) != length)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("send_n failed")),
+ -1);
+ else
+ {
+ ACE_Name_Reply reply;
+
+ // Receive reply via blocking read.
+
+ if (this->peer_.recv_n (&reply,
+ sizeof reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("recv failed")),
+ -1);
+ else if (reply.decode () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("decode failed")),
+ -1);
+ errno = int (reply.errnum ());
+ return reply.status ();
+ }
+}
+
+int
+ACE_Name_Proxy::send_request (ACE_Name_Request &request)
+{
+ ACE_TRACE ("ACE_Name_Proxy::send_request");
+ void *buffer;
+ ssize_t length = request.encode (buffer);
+
+ if (length == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("encode failed")),
+ -1);
+
+ // Transmit request via a blocking send.
+
+ else if (this->peer_.send_n (buffer, length) != length)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("send_n failed")),
+ -1);
+ return 0;
+}
+
+int
+ACE_Name_Proxy::recv_reply (ACE_Name_Request &reply)
+{
+ ACE_TRACE ("ACE_Name_Proxy::recv_reply");
+ // Read the first 4 bytes to get the length of the message This
+ // implementation assumes that the first 4 bytes are the length of
+ // the message.
+ ssize_t n = this->peer_.recv ((void *) &reply, sizeof (ACE_UINT32));
+
+ switch (n)
+ {
+ case -1:
+ // FALLTHROUGH
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("****************** recv_reply returned -1\n")));
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p got %d bytes, expected %d bytes\n"),
+ ACE_LIB_TEXT ("recv failed"),
+ n,
+ sizeof (ACE_UINT32)));
+ // FALLTHROUGH
+ case 0:
+ // We've shutdown unexpectedly
+ return -1;
+ // NOTREACHED
+ case sizeof (ACE_UINT32):
+ {
+ // Transform the length into host byte order.
+ ssize_t length = ntohl (reply.length ());
+
+ // Receive the rest of the request message.
+ // @@ beware of blocking read!!!.
+ n = this->peer_.recv ((void *) (((char *) &reply)
+ + sizeof (ACE_UINT32)),
+ length - sizeof (ACE_UINT32));
+
+ // Subtract off the size of the part we skipped over...
+ if (n != ssize_t (length - sizeof (ACE_UINT32)))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p expected %d, got %d\n"),
+ ACE_LIB_TEXT ("invalid length"),
+ length,
+ n));
+ return -1;
+ }
+
+ // Decode the request into host byte order.
+ if (reply.decode () == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("decode failed")));
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+// Close down the connection to the server.
+
+ACE_Name_Proxy::~ACE_Name_Proxy (void)
+{
+ ACE_TRACE ("ACE_Name_Proxy::~ACE_Name_Proxy");
+ this->peer_.close ();
+}
diff --git a/ace/Other/Name_Proxy.h b/ace/Other/Name_Proxy.h
new file mode 100644
index 00000000000..234f7b93c49
--- /dev/null
+++ b/ace/Other/Name_Proxy.h
@@ -0,0 +1,91 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Name_Proxy.h
+ *
+ * $Id$
+ *
+ * Proxy for dealing with remote server process managing NET_LOCAL
+ * Name_Bindings.
+ *
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt
+ * @author and Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_NAME_PROXY_H
+#define ACE_NAME_PROXY_H
+#include "ace/pre.h"
+
+#include "ace/INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Service_Config.h"
+#include "ace/Synch_Options.h"
+#include "ace/Name_Request_Reply.h"
+
+/**
+ * @class ACE_Name_Proxy
+ *
+ * @brief Proxy for dealing with remote server process managing NET_LOCAL
+ * NameBindings.
+ *
+ * Shields applications from details of interacting with the
+ * ACE_Name Server.
+ */
+class ACE_Export ACE_Name_Proxy : public ACE_Event_Handler
+{
+public:
+ /// Default constructor.
+ ACE_Name_Proxy (void);
+
+ // = Establish a binding with the ACE_Name Server.
+ ACE_Name_Proxy (const ACE_INET_Addr &remote_addr, // Address of ACE_Name Server.
+ ACE_Synch_Options& options =
+ ACE_Synch_Options::defaults);
+
+ int open (const ACE_INET_Addr &remote_addr, // Address of ACE_Name Server.
+ ACE_Synch_Options& options =
+ ACE_Synch_Options::defaults);
+
+ /// Perform the request and wait for the reply.
+ int request_reply (ACE_Name_Request &request);
+
+ /// Perform the request.
+ int send_request (ACE_Name_Request &request);
+
+ /// Receive the reply.
+ int recv_reply (ACE_Name_Request &reply);
+
+ /// Obtain underlying handle.
+ virtual ACE_HANDLE get_handle (void) const;
+
+ /// Close down the connection to the server.
+ virtual ~ACE_Name_Proxy (void);
+
+ /// Dump the state of the object;
+ void dump (void) const;
+
+private:
+
+ /// ACE_Connector factory used to establish connections actively.
+ ACE_SOCK_Connector connector_;
+
+ /// Connection to ACE_Name Server peer.
+ ACE_SOCK_Stream peer_;
+
+ /// Pointer to ACE_Reactor (used if we are run in "reactive-mode").
+ ACE_Reactor *reactor_;
+};
+
+#include "ace/post.h"
+#endif /* ACE_NAME_PROXY_H */
diff --git a/ace/Other/Name_Request_Reply.cpp b/ace/Other/Name_Request_Reply.cpp
new file mode 100644
index 00000000000..032e4771a63
--- /dev/null
+++ b/ace/Other/Name_Request_Reply.cpp
@@ -0,0 +1,556 @@
+// $Id$
+
+#include "ace/Name_Request_Reply.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Name_Request_Reply, "$Id$")
+
+// Default "do nothing" constructor.
+
+ACE_Name_Request::ACE_Name_Request (void)
+{
+ ACE_TRACE ("ACE_Name_Request::ACE_Name_Request");
+}
+
+// Create a ACE_Name_Request message.
+
+ACE_Name_Request::ACE_Name_Request (ACE_INT32 t, // Type of request.
+ const ACE_USHORT16 name[], // Name
+ const ACE_UINT32 name_length, // size in bytes
+ const ACE_USHORT16 value[], //
+ const ACE_UINT32 value_length, // size in bytes
+ const char type[], //
+ const ACE_UINT32 type_length, // size in bytes
+ ACE_Time_Value *timeout) // Max time waiting for request.
+{
+ ACE_TRACE ("ACE_Name_Request::ACE_Name_Request");
+ this->msg_type (t);
+ this->name_len (name_length);
+ this->value_len (value_length);
+ this->type_len (type_length);
+
+ // If timeout is a NULL pointer, then block forever...
+ if (timeout == 0)
+ {
+ this->transfer_.block_forever_ = 1;
+ this->transfer_.sec_timeout_ = 0;
+ this->transfer_.usec_timeout_ = 0;
+ }
+ else // Do a "timed wait."
+ {
+ this->block_forever (0);
+ // Keep track of how long client is willing to wait.
+ this->transfer_.sec_timeout_ = timeout->sec ();
+ this->transfer_.usec_timeout_ = timeout->usec ();
+ }
+
+ // Set up pointers and copy name value and type into request.
+ this->name_ = this->transfer_.data_;
+ this->value_ = &this->name_[name_length / sizeof (ACE_USHORT16) ];
+ this->type_ = (char *)(&this->value_[value_length / sizeof (ACE_USHORT16)]); //
+
+ (void) ACE_OS::memcpy (this->name_,
+ name,
+ name_length);
+ (void) ACE_OS::memcpy (this->value_,
+ value,
+ value_length);
+ (void) ACE_OS::memcpy (this->type_,
+ type,
+ type_length);
+
+ // Compute size of the fixed portion of the message...
+ size_t len = sizeof this->transfer_ - sizeof this->transfer_.data_;
+
+ // ... then add in the amount of the variable-sized portion.
+ len += name_length + value_length + type_length ;
+
+ this->length (len);
+}
+
+// Initialize length_ in order to avoid problems with byte-ordering.
+
+void
+ACE_Name_Request::init (void)
+{
+ ACE_TRACE ("ACE_Name_Request::init");
+ this->length (sizeof this->transfer_);
+}
+
+// = Set/get the length of the encoded/decoded message.
+
+ACE_UINT32
+ACE_Name_Request::length (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::length");
+ return this->transfer_.length_;
+}
+
+void
+ACE_Name_Request::length (ACE_UINT32 l)
+{
+ ACE_TRACE ("ACE_Name_Request::length");
+ this->transfer_.length_ = l;
+}
+
+// = Set/get the type of the message.
+
+ACE_INT32
+ACE_Name_Request::msg_type (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::msg_type");
+ return this->transfer_.msg_type_;
+}
+
+void
+ACE_Name_Request::msg_type (ACE_INT32 t)
+{
+ ACE_TRACE ("ACE_Name_Request::msg_type");
+ this->transfer_.msg_type_ = t;
+}
+
+// = Set/get the len of the name
+
+ACE_UINT32
+ACE_Name_Request::name_len (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::name_len");
+ return this->transfer_.name_len_;
+}
+
+void
+ACE_Name_Request::name_len (ACE_UINT32 t)
+{
+ ACE_TRACE ("ACE_Name_Request::name_len");
+ this->transfer_.name_len_ = t;
+}
+
+// = Set/get the len of the value
+
+ACE_UINT32
+ACE_Name_Request::value_len (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::value_len");
+ return this->transfer_.value_len_;
+}
+
+void
+ACE_Name_Request::value_len (ACE_UINT32 t)
+{
+ ACE_TRACE ("ACE_Name_Request::value_len");
+ this->transfer_.value_len_ = t;
+}
+
+// = Set/get the len of the type
+
+ACE_UINT32
+ACE_Name_Request::type_len (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::type_len");
+ return this->transfer_.type_len_;
+}
+
+void
+ACE_Name_Request::type_len (ACE_UINT32 t)
+{
+ ACE_TRACE ("ACE_Name_Request::type_len");
+ this->transfer_.type_len_ = t;
+}
+
+// = Set/get the blocking semantics.
+
+ACE_UINT32
+ACE_Name_Request::block_forever (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::block_forever");
+ return this->transfer_.block_forever_;
+}
+
+void
+ACE_Name_Request::block_forever (ACE_UINT32 bs)
+{
+ ACE_TRACE ("ACE_Name_Request::block_forever");
+ this->transfer_.block_forever_ = bs;
+}
+
+// = Set/get the timeout.
+
+ACE_Time_Value
+ACE_Name_Request::timeout (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::timeout");
+ return ACE_Time_Value (this->transfer_.sec_timeout_,
+ this->transfer_.usec_timeout_);
+}
+
+void
+ACE_Name_Request::timeout (const ACE_Time_Value timeout)
+{
+ ACE_TRACE ("ACE_Name_Request::timeout");
+ this->transfer_.sec_timeout_ = timeout.sec ();
+ this->transfer_.usec_timeout_ = timeout.usec ();
+}
+
+// = Set/get the name
+
+const ACE_USHORT16 *
+ACE_Name_Request::name (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::name");
+ return this->name_;
+}
+
+void
+ACE_Name_Request::name (const ACE_USHORT16 *t)
+{
+ ACE_TRACE ("ACE_Name_Request::name");
+ (void) ACE_OS::memcpy (this->name_,
+ t,
+ this->name_len ());
+}
+
+// = Set/get the value
+
+const ACE_USHORT16 *
+ACE_Name_Request::value (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::value");
+ return this->value_;
+}
+
+void
+ACE_Name_Request::value (const ACE_USHORT16 *c)
+{
+ ACE_TRACE ("ACE_Name_Request::value");
+
+ (void) ACE_OS::memcpy (this->value_,
+ c,
+ this->value_len());
+}
+
+// = Set/get the type
+
+const char *
+ACE_Name_Request::type (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::type");
+ return this->type_;
+}
+
+void
+ACE_Name_Request::type (const char *c)
+{
+ ACE_TRACE ("ACE_Name_Request::type");
+ ACE_OS::strsncpy (this->type_,
+ c,
+ sizeof this->type_);
+}
+
+// Encode the transfer buffer into network byte order so that it can
+// be sent to the server.
+
+int
+ACE_Name_Request::encode (void *&buf)
+{
+ ACE_TRACE ("ACE_Name_Request::encode");
+ // Compute the length *before* doing the marshaling.
+
+ ssize_t len = this->length ();
+
+ size_t nv_data_len =
+ (this->transfer_.name_len_ + this->transfer_.value_len_)
+ / sizeof (ACE_USHORT16);
+
+ for (size_t i = 0; i < nv_data_len; i++)
+ this->transfer_.data_[i] =
+ htons (this->transfer_.data_[i]);
+
+ buf = (void *) &this->transfer_;
+ this->transfer_.block_forever_ = htonl (this->transfer_.block_forever_);
+ this->transfer_.usec_timeout_ = htonl (this->transfer_.usec_timeout_);
+ this->transfer_.sec_timeout_ = htonl (this->transfer_.sec_timeout_);
+ this->transfer_.length_ = htonl (this->transfer_.length_);
+ this->transfer_.msg_type_ = htonl (this->transfer_.msg_type_);
+ this->transfer_.name_len_ = htonl (this->transfer_.name_len_);
+ this->transfer_.value_len_ = htonl (this->transfer_.value_len_);
+ this->transfer_.type_len_ = htonl (this->transfer_.type_len_);
+
+ return len;
+}
+
+// Decode the transfer buffer into host byte byte order so that it can
+// be used by the server.
+
+int
+ACE_Name_Request::decode (void)
+{
+ ACE_TRACE ("ACE_Name_Request::decode");
+ // Decode the fixed-sized portion first.
+ this->transfer_.block_forever_ = ntohl (this->transfer_.block_forever_);
+ this->transfer_.usec_timeout_ = ntohl (this->transfer_.usec_timeout_);
+ this->transfer_.sec_timeout_ = ntohl (this->transfer_.sec_timeout_);
+ this->transfer_.length_ = ntohl (this->transfer_.length_);
+ this->transfer_.msg_type_ = ntohl (this->transfer_.msg_type_);
+ this->transfer_.name_len_ = ntohl (this->transfer_.name_len_);
+ this->transfer_.value_len_ = ntohl (this->transfer_.value_len_);
+ this->transfer_.type_len_ = ntohl (this->transfer_.type_len_);
+
+ size_t nv_data_len =
+ (this->transfer_.name_len_ + this->transfer_.value_len_)
+ / sizeof (ACE_USHORT16);
+
+ for (size_t i = 0; i < nv_data_len; i++)
+ this->transfer_.data_[i] =
+ ntohs (this->transfer_.data_[i]);
+
+ this->name_ = this->transfer_.data_;
+ this->value_ = &this->name_[this->transfer_.name_len_ / sizeof (ACE_USHORT16)];
+ this->type_ = (char *)(&this->value_[this->transfer_.value_len_ / sizeof (ACE_USHORT16)]);
+ this->type_[this->transfer_.type_len_] = '\0';
+
+ // Decode the variable-sized portion.
+ return 0;
+}
+
+// Print out the current values of the ACE_Name_Request.
+
+void
+ACE_Name_Request::dump (void) const
+{
+ ACE_TRACE ("ACE_Name_Request::dump");
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("*******\nlength = %d\n"),
+ this->length ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("message-type = ")));
+
+ switch (this->msg_type ())
+ {
+ case ACE_Name_Request::BIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("BIND\n")));
+ break;
+ case ACE_Name_Request::REBIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("REBIND\n")));
+ break;
+ case ACE_Name_Request::RESOLVE:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("RESOLVE\n")));
+ break;
+ case ACE_Name_Request::UNBIND:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("UNBIND\n")));
+ break;
+ case ACE_Name_Request::LIST_NAMES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_NAMES\n")));
+ break;
+ case ACE_Name_Request::LIST_VALUES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_VALUES\n")));
+ break;
+ case ACE_Name_Request::LIST_TYPES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_TYPES\n")));
+ break;
+ case ACE_Name_Request::LIST_NAME_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_NAME_ENTRIES\n")));
+ break;
+ case ACE_Name_Request::LIST_VALUE_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_VALUE_ENTRIES\n")));
+ break;
+ case ACE_Name_Request::LIST_TYPE_ENTRIES:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("LIST_TYPE_ENTRIES\n")));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("<unknown type> = %d\n"),
+ this->msg_type ()));
+ break;
+ }
+
+ if (this->block_forever ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("blocking forever\n")));
+ else
+ {
+#if !defined (ACE_NLOGGING)
+ ACE_Time_Value tv = this->timeout ();
+#endif /* ! ACE_NLOGGING */
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("waiting for %d secs and %d usecs\n"),
+ tv.sec (),
+ tv.usec ()));
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("*******\nname_len = %d\n"),
+ this->name_len ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("*******\nvalue_len = %d\n"),
+ this->value_len ()));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("+++++++\n")));
+}
+
+// Default constructor.
+
+ACE_Name_Reply::ACE_Name_Reply (void)
+{
+ ACE_TRACE ("ACE_Name_Reply::ACE_Name_Reply");
+
+ // Initialize to a known quantity.
+ this->msg_type (0);
+ this->errnum (0);
+ this->length (sizeof this->transfer_);
+}
+
+// Create a ACE_Name_Reply message.
+
+ACE_Name_Reply::ACE_Name_Reply (ACE_UINT32 t, ACE_UINT32 err) // Type of reply.
+{
+ ACE_TRACE ("ACE_Name_Reply::ACE_Name_Reply");
+ this->msg_type (t);
+ this->errnum (err);
+ this->length (sizeof this->transfer_);
+}
+
+// Initialize length_ to avoid problems with byte-ordering.
+
+void
+ACE_Name_Reply::init (void)
+{
+ ACE_TRACE ("ACE_Name_Reply::init");
+ this->length (sizeof this->transfer_);
+}
+
+// = Set/get the length of the encoded/decoded message.
+
+ACE_UINT32
+ACE_Name_Reply::length (void) const
+{
+ ACE_TRACE ("ACE_Name_Reply::length");
+ return this->transfer_.length_;
+}
+
+void
+ACE_Name_Reply::length (ACE_UINT32 l)
+{
+ ACE_TRACE ("ACE_Name_Reply::length");
+ this->transfer_.length_ = l;
+}
+
+// = Set/get the type of the message.
+
+ACE_INT32
+ACE_Name_Reply::msg_type (void) const
+{
+ ACE_TRACE ("ACE_Name_Reply::msg_type");
+ return this->transfer_.type_;
+}
+
+void
+ACE_Name_Reply::msg_type (ACE_INT32 t)
+{
+ ACE_TRACE ("ACE_Name_Reply::msg_type");
+ this->transfer_.type_ = t;
+}
+
+// Get the status of the reply (0 == success, -1 == failure).
+
+ACE_INT32
+ACE_Name_Reply::status (void) const
+{
+ ACE_TRACE ("ACE_Name_Reply::status");
+ return this->transfer_.type_;
+}
+
+// Set the status of the reply (0 == success, -1 == failure).
+
+void
+ACE_Name_Reply::status (ACE_INT32 s)
+{
+ ACE_TRACE ("ACE_Name_Reply::status");
+ if (s == -1)
+ this->transfer_.type_ = -1;
+ else
+ this->transfer_.type_ = 0;
+}
+
+// = Set/get the errno of a failed reply.
+ACE_UINT32
+ACE_Name_Reply::errnum (void) const
+{
+ ACE_TRACE ("ACE_Name_Reply::errnum");
+ return this->transfer_.errno_;
+}
+
+void
+ACE_Name_Reply::errnum (ACE_UINT32 e)
+{
+ ACE_TRACE ("ACE_Name_Reply::errnum");
+ this->transfer_.errno_ = e;
+}
+
+// Encode the transfer buffer into network byte order
+// so that it can be sent to the client.
+
+int
+ACE_Name_Reply::encode (void *&buf)
+{
+ ACE_TRACE ("ACE_Name_Reply::encode");
+ int len = this->length (); // Get length *before* marshaling.
+
+ this->transfer_.length_ = htonl (this->transfer_.length_);
+ this->transfer_.type_ = htonl (this->transfer_.type_);
+ this->transfer_.errno_ = htonl (this->transfer_.errno_);
+ buf = (void *) &this->transfer_;
+ return len;
+}
+
+// Decode the transfer buffer into host byte order so that it can be
+// used by the client.
+
+int
+ACE_Name_Reply::decode (void)
+{
+ ACE_TRACE ("ACE_Name_Reply::decode");
+ this->transfer_.length_ = ntohl (this->transfer_.length_);
+ this->transfer_.type_ = ntohl (this->transfer_.type_);
+ this->transfer_.errno_ = ntohl (this->transfer_.errno_);
+ return 0;
+}
+
+// Print out current values of the ACE_Name_Reply object.
+
+void
+ACE_Name_Reply::dump (void) const
+{
+ ACE_TRACE ("ACE_Name_Reply::dump");
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("*******\nlength = %d\nerrnum = %d"),
+ this->length (),
+ this->errnum ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("type = ")));
+ switch (this->msg_type ())
+ {
+ case 0:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("SUCCESS\n")));
+ break;
+ case -1:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("FAILURE\n")));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("<unknown type> = %d\n"),
+ this->msg_type ()));
+ break;
+ }
+}
diff --git a/ace/Other/Name_Request_Reply.h b/ace/Other/Name_Request_Reply.h
new file mode 100644
index 00000000000..43dd8609187
--- /dev/null
+++ b/ace/Other/Name_Request_Reply.h
@@ -0,0 +1,260 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Name_Request_Reply.h
+ *
+ * $Id$
+ *
+ * Define the format used to exchange messages between the
+ * ACE_Name Server and its clients.
+ *
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt
+ * @author and Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_NAME_REQUEST_REPLY_H
+#define ACE_NAME_REQUEST_REPLY_H
+#include "ace/pre.h"
+
+#include "ace/Time_Value.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+
+/**
+ * @class ACE_Name_Request
+ *
+ * @brief Message format for delivering requests to the ACE_Name Server.
+ *
+ * This class is implemented to minimize data copying. In
+ * particular, all marshaling is done in situ...
+ */
+class ACE_Export ACE_Name_Request
+{
+public:
+ /// Request message types.
+ enum Constants
+ {
+ BIND = 01,
+ REBIND = 02,
+ RESOLVE = 03,
+ UNBIND = 04,
+ LIST_NAMES = 05,
+ LIST_VALUES = 015,
+ LIST_TYPES = 025,
+ LIST_NAME_ENTRIES = 06,
+ LIST_VALUE_ENTRIES = 016,
+ LIST_TYPE_ENTRIES = 026,
+ MAX_ENUM = 11,
+ MAX_LIST = 3,
+
+ // Mask for bitwise operation used for table lookup
+ /// Mask for lookup of operation
+ OP_TABLE_MASK = 07,
+ /// Mask for lookup of list_operation
+ LIST_OP_MASK = 030,
+
+ /// Class-specific constant values.
+ MAX_NAME_LENGTH = MAXPATHLEN + 1
+ };
+
+ /// Default constructor.
+ ACE_Name_Request (void);
+
+ /// Create a <ACE_Name_Request> message.
+ ACE_Name_Request (ACE_INT32 msg_type, // Type of request.
+ const ACE_USHORT16 name[], //
+ const ACE_UINT32 name_length,
+ const ACE_USHORT16 value[],
+ const ACE_UINT32 value_length,
+ const char type[],
+ const ACE_UINT32 type_length,
+ ACE_Time_Value *timeout = 0); // Max time willing to wait for request.
+
+ /// Initialize length_ in order to ensure correct byte ordering
+ /// before a request is sent.
+ void init (void);
+
+ // = Set/get the length of the encoded/decoded message.
+ ACE_UINT32 length (void) const;
+ void length (ACE_UINT32);
+
+ // = Set/get the type of the message.
+ ACE_INT32 msg_type (void) const;
+ void msg_type (ACE_INT32);
+
+ // = Set/get the blocking semantics.
+ ACE_UINT32 block_forever (void) const;
+ void block_forever (ACE_UINT32);
+
+ // = Set/get the timeout.
+ ACE_Time_Value timeout (void) const;
+ void timeout (const ACE_Time_Value timeout);
+
+ // = Set/get the name
+ const ACE_USHORT16 *name (void) const;
+ void name (const ACE_USHORT16 *);
+
+ // = Set/get the value
+ const ACE_USHORT16 *value (void) const;
+ void value (const ACE_USHORT16 *);
+
+ // = Set/get the type
+ const char *type (void) const;
+ void type (const char *);
+
+ // = Set/get the len of name
+ ACE_UINT32 name_len (void) const;
+ void name_len (ACE_UINT32);
+
+ // = Set/get the len of value
+ ACE_UINT32 value_len (void) const;
+ void value_len (ACE_UINT32);
+
+ // = Set/get the len of type
+ ACE_UINT32 type_len (void) const;
+ void type_len (ACE_UINT32);
+
+ /// Encode the message before transmission.
+ int encode (void *&);
+
+ /// Decode message after reception.
+ int decode (void);
+
+ /// Print out the values of the message for debugging purposes.
+ void dump (void) const;
+
+private:
+ // = The 5 fields in the <Transfer> struct are transmitted to the server.
+ // The remaining 2 fields are not tranferred -- they are used only on
+ // the server-side to simplify lookups.
+
+ struct Transfer
+ {
+ ACE_UINT32 length_;
+ // Length of entire request.
+
+ ACE_UINT32 msg_type_;
+ // Type of the request (i.e., <BIND>, <REBIND>, <RESOLVE>, and <UNBIND>).
+
+ ACE_UINT32 block_forever_;
+ // Indicates if we should block forever. If 0, then <secTimeout_>
+ // and <usecTimeout_> indicates how long we should wait.
+
+ ACE_UINT32 sec_timeout_;
+ // Max seconds willing to wait for name if not blocking forever.
+
+ ACE_UINT32 usec_timeout_;
+ // Max micro seconds to wait for name if not blocking forever.
+
+ ACE_UINT32 name_len_;
+ // Len of name in bytes
+
+ ACE_UINT32 value_len_;
+ // Len of value in bytes
+
+ ACE_UINT32 type_len_;
+ // Len of type in bytes
+
+ ACE_USHORT16 data_[MAX_NAME_LENGTH + MAXPATHLEN + MAXPATHLEN + 2];
+ // The data portion contains the <name_>
+ // followed by the <value_>
+ // followed by the <type_>.
+ };
+
+ /// Transfer buffer.
+ Transfer transfer_;
+
+ /// Pointer to the beginning of the name in this->data_.
+ ACE_USHORT16 *name_;
+
+ /// Pointer to the beginning of the value in this->data_;
+ ACE_USHORT16 *value_;
+
+ /// Pointer to the beginning of the type in this->data_;
+ char *type_;
+};
+
+/**
+ * @class ACE_Name_Reply
+ *
+ * @brief Message format for delivering replies from the ACE_Name Server.
+ *
+ * This class is implemented to minimize data copying. In
+ * particular, all marshaling is done in situ...
+ */
+class ACE_Export ACE_Name_Reply
+{
+public:
+ enum Constants
+ {
+ /// Class-specific constant values.
+ MAX_NAME_LENGTH = MAXPATHLEN + 1
+ };
+
+ /// Default constructor.
+ ACE_Name_Reply (void);
+
+ /// Create a <ACE_Name_Reply> message.
+ ACE_Name_Reply (ACE_UINT32 type, ACE_UINT32 err); // Type of reply.
+
+ /// Initialize length_ in order to ensure correct byte ordering
+ /// before a reply is sent.
+ void init (void);
+
+ // = Set/get the length of the encoded/decoded message.
+ ACE_UINT32 length (void) const;
+ void length (ACE_UINT32);
+
+ // = Set/get the type of the message.
+ ACE_INT32 msg_type (void) const;
+ void msg_type (ACE_INT32);
+
+ // = Set/get the status of the reply (0 == success, -1 == failure).
+ ACE_INT32 status (void) const;
+ void status (ACE_INT32);
+
+ // = Set/get the errno of a failed reply.
+ ACE_UINT32 errnum (void) const;
+ void errnum (ACE_UINT32);
+
+ /// Encode the message before transfer.
+ int encode (void *&);
+
+ /// Decode a message after reception.
+ int decode (void);
+
+ /// Print out the values of the message for debugging purposes.
+ void dump (void) const;
+
+private:
+ // = The 3 fields in the <Transfer> struct are transmitted to the server.
+
+ struct Transfer
+ {
+ ACE_UINT32 length_;
+ // Length of entire reply.
+
+ ACE_INT32 type_;
+ // Type of the reply, i.e., success (0) or failure (-1).
+
+ ACE_UINT32 errno_;
+ // Indicates why error occurred if <this->type_> == failure (-1).
+ // Typical reasons include: <ETIME> (if the client timed out after
+ // waiting for the name).
+ };
+
+ /// Transfer buffer.
+ Transfer transfer_;
+};
+
+#include "ace/post.h"
+#endif /* ACE_NAME_REQUEST_REPLY_H */
diff --git a/ace/Other/Name_Space.cpp b/ace/Other/Name_Space.cpp
new file mode 100644
index 00000000000..363790eac5a
--- /dev/null
+++ b/ace/Other/Name_Space.cpp
@@ -0,0 +1,61 @@
+// Name_Space.cpp
+// $Id$
+
+#include "ace/Name_Space.h"
+
+ACE_RCSID(ace, Name_Space, "$Id$")
+
+ACE_Name_Binding::ACE_Name_Binding (void)
+ : type_ (ACE_OS::strdup (""))
+{
+ ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding");
+}
+
+
+ACE_Name_Binding::~ACE_Name_Binding (void)
+{
+ ACE_TRACE ("ACE_Name_Binding::~ACE_Name_Binding");
+ ACE_OS::free ((void *) this->type_);
+}
+
+ACE_Name_Binding::ACE_Name_Binding (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+ : name_ (name),
+ value_ (value),
+ type_ (type == 0 ? ACE_OS::strdup ("") : ACE_OS::strdup (type))
+{
+ ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding");
+}
+
+ACE_Name_Binding::ACE_Name_Binding (const ACE_Name_Binding &s)
+ : name_ (s.name_),
+ value_ (s.value_),
+ type_ (ACE_OS::strdup (s.type_))
+{
+ ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding");
+}
+
+void
+ACE_Name_Binding::operator = (const ACE_Name_Binding &s)
+{
+ ACE_TRACE ("ACE_Name_Binding::operator =");
+
+ this->name_ = s.name_;
+ this->value_ = s.value_;
+ this->type_ = ACE_OS::strdup (s.type_);
+}
+
+int
+ACE_Name_Binding::operator == (const ACE_Name_Binding &s) const
+{
+ ACE_TRACE ("ACE_Name_Binding::operator ==");
+ return this->name_ == s.name_
+ && this->value_ == s.value_
+ && ACE_OS::strcmp (this->type_, s.type_) == 0;
+}
+
+ACE_Name_Space::~ACE_Name_Space (void)
+{
+ ACE_TRACE ("ACE_Name_Space::~ACE_Name_Space");
+}
diff --git a/ace/Other/Name_Space.h b/ace/Other/Name_Space.h
new file mode 100644
index 00000000000..d4e461750a8
--- /dev/null
+++ b/ace/Other/Name_Space.h
@@ -0,0 +1,161 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_NAME_SPACE_H
+#define ACE_NAME_SPACE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Unbounded_Set.h"
+#include "ace/Name_Proxy.h"
+
+typedef ACE_Unbounded_Set<ACE_NS_WString> ACE_WSTRING_SET;
+
+/**
+ * @class ACE_Name_Binding
+ *
+ * @brief Maintains a mapping from name to value and type.
+ */
+class ACE_Export ACE_Name_Binding
+{
+public:
+ // = Initialization and termination.
+ /// Main constructor that initializes all the fields.
+ ACE_Name_Binding (const ACE_NS_WString &n,
+ const ACE_NS_WString &v,
+ const char *t);
+
+ /// Default constructor.
+ ACE_Name_Binding (void);
+
+ /// Copy constructor.
+ ACE_Name_Binding (const ACE_Name_Binding &);
+
+ /// Assignment operator.
+ void operator= (const ACE_Name_Binding &);
+
+ /// Destructor.
+ ~ACE_Name_Binding (void);
+
+ /// Test for equality.
+ int operator == (const ACE_Name_Binding &s) const;
+
+ /// Name of the binding.
+ ACE_NS_WString name_;
+
+ /// Value of the binding.
+ ACE_NS_WString value_;
+
+ /// Type of the binding.
+ char *type_;
+};
+
+typedef ACE_Unbounded_Set<ACE_Name_Binding> ACE_BINDING_SET;
+typedef ACE_Unbounded_Set_Iterator<ACE_Name_Binding> ACE_BINDING_ITERATOR;
+
+typedef ACE_Unbounded_Set<ACE_NS_WString> ACE_PWSTRING_SET;
+typedef ACE_Unbounded_Set_Iterator<ACE_NS_WString> ACE_PWSTRING_ITERATOR;
+
+/**
+ * @class ACE_Name_Space
+ *
+ * @brief Abstract base class that provides an abstract interface to
+ * the database without exposing any implemenation details.
+ *
+ * Manages a Naming Service Name Space. Provides the basic
+ * methods -- bind, unbind, rebind, find, and listnames.
+ */
+class ACE_Export ACE_Name_Space
+{
+public:
+
+ /// virtual destructor to ensure destructors of subclasses get
+ /// called.
+ virtual ~ACE_Name_Space (void);
+
+ /// Bind a new name to a naming context (Wide character strings).
+ virtual int bind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "") = 0;
+
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Name_Space or bind a new name to the context, if it didn't
+ * exist yet. (Wide charcter strings interface).
+ */
+ virtual int rebind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "") = 0;
+
+ /// Delete a name from a ACE_Name_Space (Wide charcter strings
+ /// Interface).
+ virtual int unbind (const ACE_NS_WString &name_in) = 0;
+
+ /// Get value and type of a given name binding (Wide chars). The
+ /// caller is responsible for deleting both <value_out> and <type_out>!
+ virtual int resolve (const ACE_NS_WString &name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out) = 0;
+
+ /// Get a set of names matching a specified pattern (wchars). Matching
+ /// means the names must begin with the pattern string.
+ virtual int list_names (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in) = 0;
+
+ /// Get a set of values matching a specified pattern (wchars). Matching
+ /// means the values must begin with the pattern string.
+ virtual int list_values (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in) = 0;
+
+ /// Get a set of types matching a specified pattern (wchars). Matching
+ /// means the types must begin with the pattern string.
+ virtual int list_types (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in) = 0;
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern) = 0;
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern) = 0;
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern) = 0;
+
+ /// Dump the state of the object
+ virtual void dump (void) const = 0;
+};
+
+#include "ace/post.h"
+#endif /* ACE_NAME_SPACE_H */
diff --git a/ace/Other/Naming_Context.cpp b/ace/Other/Naming_Context.cpp
new file mode 100644
index 00000000000..ccfe614ea8b
--- /dev/null
+++ b/ace/Other/Naming_Context.cpp
@@ -0,0 +1,693 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/Naming_Context.h"
+#include "ace/Remote_Name_Space.h"
+#include "ace/Local_Name_Space_T.h"
+#include "ace/Registry_Name_Space.h"
+#include "ace/Memory_Pool.h"
+#include "ace/RW_Process_Mutex.h"
+
+ACE_RCSID(ace, Naming_Context, "$Id$")
+
+// Make life easier later on...
+
+typedef ACE_Local_Name_Space <ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> LOCAL_NAME_SPACE;
+typedef ACE_Local_Name_Space <ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> LITE_LOCAL_NAME_SPACE;
+
+// The following Factory is used by the ACE_Service_Config and
+// svc.conf file to dynamically initialize the state of the Name
+// Server client.
+
+ACE_FACTORY_DEFINE (ACE, ACE_Naming_Context)
+ACE_STATIC_SVC_DEFINE (ACE_Naming_Context,
+ ACE_LIB_TEXT ("ACE_Naming_Context"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (ACE_Naming_Context),
+ ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ,
+ 0)
+ACE_STATIC_SVC_REQUIRE (ACE_Naming_Context)
+
+// The ACE_Naming_Context static service object is now defined
+// by the ACE_Object_Manager, in Object_Manager.cpp.
+
+int
+ACE_Naming_Context::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TRACE ("ACE_Naming_Context::info");
+ ACE_UNUSED_ARG (length);
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::sprintf (buf,
+ ACE_LIB_TEXT ("%s\t#%s\n"),
+ ACE_LIB_TEXT ("ACE_Naming_Context"),
+ ACE_LIB_TEXT ("Proxy for making calls to a Name Server"));
+
+ if (*strp == 0 && (*strp = ACE_OS_String::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS_String::strsncpy (*strp, buf, length);
+ return ACE_OS_String::strlen (buf);
+}
+
+int
+ACE_Naming_Context::local (void)
+{
+ ACE_TRACE ("ACE_Naming_Context::local");
+ return ACE_OS::strcmp (this->netnameserver_host_,
+ ACE_LIB_TEXT ("localhost")) == 0
+ || ACE_OS::strcmp (this->netnameserver_host_,
+ this->hostname_) == 0;
+}
+
+int
+ACE_Naming_Context::open (Context_Scope_Type scope_in, int lite)
+{
+ ACE_TRACE ("ACE_Naming_Context::open");
+ ACE_OS::hostname (this->hostname_,
+ (sizeof this->hostname_ / sizeof (ACE_TCHAR)));
+
+ this->netnameserver_host_ =
+ this->name_options_->nameserver_host ();
+ this->netnameserver_port_ =
+ this->name_options_->nameserver_port ();
+
+ // Perform factory operation to select appropriate type of
+ // Name_Space subclass.
+
+#if (defined (ACE_WIN32) && defined (UNICODE))
+// This only works on Win32 platforms when UNICODE is turned on
+
+ if (this->name_options_->use_registry ())
+ // Use ACE_Registry
+ ACE_NEW_RETURN (this->name_space_,
+ ACE_Registry_Name_Space (this->name_options_),
+ -1);
+#endif /* ACE_WIN32 && UNICODE */
+ if (!this->name_options_->use_registry ())
+ if (scope_in == ACE_Naming_Context::NET_LOCAL && this->local () == 0)
+ {
+ // Use NET_LOCAL name space, set up connection with remote server.
+ ACE_NEW_RETURN (this->name_space_,
+ ACE_Remote_Name_Space (this->netnameserver_host_,
+ (u_short) this->netnameserver_port_),
+ -1);
+ }
+ else // Use NODE_LOCAL or PROC_LOCAL name space.
+ {
+ if (lite)
+ ACE_NEW_RETURN (this->name_space_,
+ LITE_LOCAL_NAME_SPACE (scope_in,
+ this->name_options_),
+ -1);
+ else
+ ACE_NEW_RETURN (this->name_space_,
+ LOCAL_NAME_SPACE (scope_in,
+ this->name_options_),
+ -1);
+ }
+
+ if (ACE_LOG_MSG->op_status () != 0 || this->name_space_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("NAME_SPACE::NAME_SPACE\n")),
+ -1);
+ return 0;
+}
+
+int
+ACE_Naming_Context::close_down (void)
+{
+ ACE_TRACE ("ACE_Naming_Context::close_down");
+
+ delete this->name_options_;
+ this->name_options_ = 0;
+
+ return this->close ();
+}
+
+int
+ACE_Naming_Context::close (void)
+{
+ ACE_TRACE ("ACE_Naming_Context::close");
+
+ delete this->name_space_;
+ this->name_space_ = 0;
+
+ return 0;
+}
+
+ACE_Naming_Context::ACE_Naming_Context (void)
+ : name_options_ (0),
+ name_space_ (0)
+{
+ ACE_TRACE ("ACE_Naming_Context::ACE_Naming_Context");
+
+ ACE_NEW (this->name_options_,
+ ACE_Name_Options);
+}
+
+ACE_Naming_Context::ACE_Naming_Context (Context_Scope_Type scope_in,
+ int lite)
+ : name_options_ (0),
+ name_space_ (0)
+{
+ ACE_TRACE ("ACE_Naming_Context::ACE_Naming_Context");
+
+ ACE_NEW (this->name_options_,
+ ACE_Name_Options);
+
+ // Initialize.
+ if (this->open (scope_in, lite) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Naming_Context::ACE_Naming_Context")));
+}
+
+ACE_Name_Options *
+ACE_Naming_Context::name_options (void)
+{
+ return this->name_options_;
+}
+
+int
+ACE_Naming_Context::bind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::bind");
+ return this->name_space_->bind (name_in, value_in, type_in);
+}
+
+int
+ACE_Naming_Context::bind (const char *name_in,
+ const char *value_in,
+ const char *type_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::bind");
+ return this->bind (ACE_NS_WString (name_in),
+ ACE_NS_WString (value_in),
+ type_in);
+}
+
+int
+ACE_Naming_Context::rebind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::rebind");
+ return this->name_space_->rebind (name_in,
+ value_in,
+ type_in);
+}
+
+int
+ACE_Naming_Context::rebind (const char *name_in,
+ const char *value_in,
+ const char *type_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::rebind");
+ return rebind (ACE_NS_WString (name_in),
+ ACE_NS_WString (value_in),
+ type_in);
+}
+
+int
+ACE_Naming_Context::resolve (const ACE_NS_WString &name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out)
+{
+ ACE_TRACE ("ACE_Naming_Context::resolve");
+ return this->name_space_->resolve (name_in,
+ value_out,
+ type_out);
+}
+
+int
+ACE_Naming_Context::resolve (const char *name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out)
+{
+ ACE_TRACE ("ACE_Naming_Context::resolve");
+ return this->resolve (ACE_NS_WString (name_in),
+ value_out,
+ type_out);
+}
+
+int
+ACE_Naming_Context::resolve (const char *name_in,
+ char *&value_out,
+ char *&type_out)
+{
+ ACE_TRACE ("ACE_Naming_Context::resolve");
+ ACE_NS_WString val_str;
+
+ if (this->resolve (ACE_NS_WString (name_in),
+ val_str,
+ type_out) == -1)
+ return -1;
+
+ // Note that <char_rep> *allocates* the memory! Thus, caller is
+ // responsible for deleting it!
+ value_out = val_str.char_rep ();
+
+ return value_out == 0 ? -1 : 0;
+}
+
+int
+ACE_Naming_Context::unbind (const ACE_NS_WString &name_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::unbind");
+ return this->name_space_->unbind (name_in);
+}
+
+int
+ACE_Naming_Context::unbind (const char *name_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::unbind");
+ return this->unbind (ACE_NS_WString (name_in));
+}
+
+int
+ACE_Naming_Context::list_names (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_names");
+ return this->name_space_->list_names (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_names (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_names");
+ return this->list_names (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+int
+ACE_Naming_Context::list_values (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_values");
+ return this->name_space_->list_values (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_values (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_values");
+ return this->list_values (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+int
+ACE_Naming_Context::list_types (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_types");
+ return this->name_space_->list_types (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_types (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_types");
+ return this->list_types (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+int
+ACE_Naming_Context::list_name_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_name_entries");
+ return this->name_space_->list_name_entries (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_name_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_name_entries");
+ return this->list_name_entries (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+int
+ACE_Naming_Context::list_value_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_value_entries");
+ return this->name_space_->list_value_entries (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_value_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_value_entries");
+ return this->list_value_entries (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+int
+ACE_Naming_Context::list_type_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_type_entries");
+ return this->name_space_->list_type_entries (set_out,
+ pattern_in);
+}
+
+int
+ACE_Naming_Context::list_type_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in)
+{
+ ACE_TRACE ("ACE_Naming_Context::list_type_entries");
+ return this->list_type_entries (set_out,
+ ACE_NS_WString (pattern_in));
+}
+
+ACE_Naming_Context::~ACE_Naming_Context (void)
+{
+ ACE_TRACE ("ACE_Naming_Context::~ACE_Naming_Context");
+
+ this->close_down ();
+}
+
+void
+ACE_Naming_Context::dump ()
+{
+ ACE_TRACE ("ACE_Naming_Context::dump");
+ this->name_space_->dump();
+}
+
+int
+ACE_Naming_Context::init (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_Naming_Context::init\n")));
+ this->name_options_->parse_args (argc, argv);
+ return this->open (this->name_options_->context ());
+}
+
+int
+ACE_Naming_Context::fini (void)
+{
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE_Naming_Context::fini\n")));
+ this->close_down ();
+ return 0;
+}
+
+ACE_Name_Options::ACE_Name_Options (void)
+ : debugging_ (0),
+ verbosity_ (0),
+ use_registry_ (0),
+ nameserver_port_ (ACE_DEFAULT_SERVER_PORT),
+ nameserver_host_ (ACE_OS::strdup (ACE_DEFAULT_SERVER_HOST)),
+ process_name_ (0),
+ database_ (ACE_OS::strdup (ACE_DEFAULT_LOCALNAME)),
+ base_address_ (ACE_DEFAULT_BASE_ADDR)
+{
+ ACE_TRACE ("ACE_Name_Options::ACE_Name_Options");
+
+#if defined (ACE_DEFAULT_NAMESPACE_DIR)
+ this->namespace_dir_ = ACE_OS::strdup (ACE_DEFAULT_NAMESPACE_DIR);
+#else /* ACE_DEFAULT_NAMESPACE_DIR */
+ size_t pathsize = (MAXPATHLEN + 1) * sizeof (ACE_TCHAR);
+ this->namespace_dir_ = ACE_static_cast (ACE_TCHAR *, ACE_OS::malloc (pathsize));
+
+ if (ACE_Lib_Find::get_temp_dir (this->namespace_dir_, MAXPATHLEN) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Temporary path too long, ")
+ ACE_LIB_TEXT ("defaulting to current directory\n")));
+ ACE_OS::strcat (this->namespace_dir_, ACE_LIB_TEXT ("."));
+ ACE_OS::strcat (this->namespace_dir_, ACE_DIRECTORY_SEPARATOR_STR);
+ }
+#endif /* ACE_DEFAULT_NAMESPACE_DIR */
+}
+
+ACE_Name_Options::~ACE_Name_Options (void)
+{
+ ACE_TRACE ("ACE_Name_Options::~ACE_Name_Options");
+
+ ACE_OS::free ((void *) this->nameserver_host_);
+ ACE_OS::free ((void *) this->namespace_dir_ );
+ ACE_OS::free ((void *) this->process_name_ );
+ ACE_OS::free ((void *) this->database_ );
+}
+
+void
+ACE_Name_Options::nameserver_port (int port)
+{
+ ACE_TRACE ("ACE_Name_Options::nameserver_port");
+ this->nameserver_port_ = port;
+}
+
+int
+ACE_Name_Options::nameserver_port (void)
+{
+ ACE_TRACE ("ACE_Name_Options::nameserver_port");
+ return this->nameserver_port_;
+}
+
+void
+ACE_Name_Options::namespace_dir (const ACE_TCHAR *dir)
+{
+ ACE_TRACE ("ACE_Name_Options::namespace_dir");
+ ACE_OS::free ((void *) this->namespace_dir_ );
+ this->namespace_dir_ = ACE_OS::strdup (dir);
+}
+
+void
+ACE_Name_Options::process_name (const ACE_TCHAR *pname)
+{
+ ACE_TRACE ("ACE_Name_Options::process_name");
+ const ACE_TCHAR *t = ACE::basename (pname, ACE_DIRECTORY_SEPARATOR_CHAR);
+ ACE_OS::free ((void *) this->process_name_ );
+ this->process_name_ = ACE_OS::strdup (t);
+}
+
+void
+ACE_Name_Options::nameserver_host (const ACE_TCHAR *host)
+{
+ ACE_TRACE ("ACE_Name_Options::nameserver_host");
+ ACE_OS::free ((void *) this->nameserver_host_);
+ this->nameserver_host_ = ACE_OS::strdup (host);
+}
+
+const ACE_TCHAR *
+ACE_Name_Options::nameserver_host (void)
+{
+ ACE_TRACE ("ACE_Name_Options::nameserver_host");
+ return this->nameserver_host_;
+}
+
+const ACE_TCHAR *
+ACE_Name_Options::database (void)
+{
+ ACE_TRACE ("ACE_Name_Options::database");
+ return this->database_;
+}
+
+void
+ACE_Name_Options::database (const ACE_TCHAR *db)
+{
+ ACE_TRACE ("ACE_Name_Options::database");
+ ACE_OS::free ((void *) this->database_);
+ this->database_ = ACE_OS::strdup (db);
+}
+
+char *
+ACE_Name_Options::base_address (void)
+{
+ ACE_TRACE ("ACE_Name_Options::base_address");
+ return this->base_address_;
+}
+
+void
+ACE_Name_Options::base_address (char *base_address)
+{
+ ACE_TRACE ("ACE_Name_Options::base_address");
+ // HP-UX 11, aC++ has a bug with 64-bit pointer initialization from
+ // a literal. To work around it, assign the literal to a long, then
+ // to the pointer. This is allegedly fixed in aC++ A.03.10.
+#if defined (__hpux) && defined(__LP64__)
+ long temp = ACE_DEFAULT_BASE_ADDRL;
+ base_address = (char *) temp;
+#endif /* defined (__hpux) && defined(__LP64__) */
+ this->base_address_ = base_address;
+}
+
+ACE_Naming_Context::Context_Scope_Type
+ACE_Name_Options::context (void)
+{
+ ACE_TRACE ("ACE_Name_Options::context");
+ return this->context_;
+}
+
+void
+ACE_Name_Options::context (ACE_Naming_Context::Context_Scope_Type context)
+{
+ ACE_TRACE ("ACE_Name_Options::context");
+ this->context_ = context;
+}
+
+const ACE_TCHAR *
+ACE_Name_Options::process_name (void)
+{
+ ACE_TRACE ("ACE_Name_Options::process_name");
+ return this->process_name_;
+}
+
+const ACE_TCHAR *
+ACE_Name_Options::namespace_dir (void)
+{
+ ACE_TRACE ("ACE_Name_Options::namespace_dir");
+ return this->namespace_dir_;
+}
+
+int
+ACE_Name_Options::debug (void)
+{
+ ACE_TRACE ("ACE_Name_Options::debug");
+ return this->debugging_;
+}
+
+int
+ACE_Name_Options::use_registry (void)
+{
+ ACE_TRACE ("ACE_Name_Options::use_registry");
+ return this->use_registry_;
+}
+
+void
+ACE_Name_Options::use_registry (int x)
+{
+ ACE_TRACE ("ACE_Name_Options::use_registry");
+ this->use_registry_ = x;
+}
+
+int
+ACE_Name_Options::verbose (void)
+{
+ ACE_TRACE ("ACE_Name_Options::verbose");
+ return this->verbosity_;
+}
+
+void
+ACE_Name_Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Name_Options::parse_args");
+ ACE_LOG_MSG->open (argv[0]);
+ this->process_name (argv[0]);
+
+ // Default is to use the PROC_LOCAL context...
+ this->context (ACE_Naming_Context::PROC_LOCAL);
+
+ // Make the database name the same as the process name by default
+ // (note that this makes a copy of the process_name_ so that we can
+ // clean it up in the destructor).
+ this->database (this->process_name ());
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_LIB_TEXT ("b:c:dh:l:P:p:s:T:vr"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'c':
+ {
+ if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_LIB_TEXT ("PROC_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::PROC_LOCAL);
+ else if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_LIB_TEXT ("NODE_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::NODE_LOCAL);
+ else if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_LIB_TEXT ("NET_LOCAL")) == 0)
+ this->context (ACE_Naming_Context::NET_LOCAL);
+ }
+ break;
+ case 'd':
+ this->debugging_ = 1;
+ break;
+ case 'r':
+ this->use_registry_ = 1;
+ break;
+ case 'h':
+ this->nameserver_host (get_opt.opt_arg ());
+ break;
+ case 'l':
+ this->namespace_dir (get_opt.opt_arg ());
+ break;
+ case 'P':
+ this->process_name (get_opt.opt_arg ());
+ break;
+ case 'p':
+ this->nameserver_port (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's':
+ this->database (get_opt.opt_arg ());
+ break;
+ case 'b':
+ this->base_address (ACE_reinterpret_cast (char *, ACE_OS::atoi (get_opt.opt_arg ())));
+ break;
+ case 'T':
+ if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_LIB_TEXT ("ON")) == 0)
+ ACE_Trace::start_tracing ();
+ else if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_LIB_TEXT ("OFF")) == 0)
+ ACE_Trace::stop_tracing ();
+ break;
+ case 'v':
+ this->verbosity_ = 1;
+ break;
+ default:
+ ACE_OS::fprintf (stderr, "%s\n"
+ "\t[-d] (enable debugging)\n"
+ "\t[-h nameserver host]\n"
+ "\t[-l namespace directory]\n"
+ "\t[-P processname]\n"
+ "\t[-p nameserver port]\n"
+ "\t[-s database name]\n"
+ "\t[-b base address]\n"
+ "\t[-v] (verbose) \n"
+ "\t[-r] (use Win32 Registry) \n",
+ argv[0]);
+ /* NOTREACHED */
+ break;
+ }
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Local_Name_Space <ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>;
+template class ACE_Local_Name_Space <ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>;
+template class ACE_Malloc<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>;
+template class ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>;
+template class ACE_Malloc_T<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex, ACE_Control_Block>;
+template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex, ACE_Control_Block>;
+template class ACE_Allocator_Adapter<ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> >;
+template class ACE_Allocator_Adapter<ACE_Malloc<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> >;
+template class ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> > >;
+template class ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> > >;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Local_Name_Space <ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Local_Name_Space <ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Malloc<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex>
+#pragma instantiate ACE_Malloc_T<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex, ACE_Control_Block>
+#pragma instantiate ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex, ACE_Control_Block>
+#pragma instantiate ACE_Allocator_Adapter<ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> >
+#pragma instantiate ACE_Allocator_Adapter<ACE_Malloc<ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> >
+#pragma instantiate ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> > >
+#pragma instantiate ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_LITE_MMAP_MEMORY_POOL, ACE_RW_Process_Mutex> > >
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Other/Naming_Context.h b/ace/Other/Naming_Context.h
new file mode 100644
index 00000000000..605eb7e8e9e
--- /dev/null
+++ b/ace/Other/Naming_Context.h
@@ -0,0 +1,364 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Naming_Context.h
+ *
+ * $Id$
+ *
+ * @author Gerhard Lenzer
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author and Prashant Jain <pjain@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_NAMING_CONTEXT_H
+#define ACE_NAMING_CONTEXT_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Containers.h"
+#include "ace/Service_Object.h"
+#include "ace/Name_Proxy.h"
+#include "ace/Name_Space.h"
+
+// Forward decl
+class ACE_Name_Options;
+
+/**
+ * @class ACE_Naming_Context
+ *
+ * @brief Maintaining accesses Name Server Databases. Allows to add
+ * NameBindings, change them, remove them and resolve
+ * NameBindings
+ *
+ * Manages a Naming Service . That represents a persistent
+ * string to string mapping for different scopes. The scope of a
+ * ACE_Naming_Context may be either local for the calling
+ * process (Note : A process is hereby not identified by it's
+ * pid, but by it's argv[0]. So different processes (in UNIX
+ * syntax) may access the same NameBindings), global for all
+ * processes running on one host or global for all processes on
+ * the net (that know the address of the net name server
+ * socket). Strings may be plain character strings or Wide
+ * character strings. A Name Binding consists of a name string
+ * (that's the key), a value string and an optional type string
+ * (no wide chars).
+ */
+class ACE_Export ACE_Naming_Context : public ACE_Service_Object
+{
+public:
+ enum Context_Scope_Type
+ {
+ /// Name lookup is local to the process.
+ PROC_LOCAL,
+ /// Name lookup is local to the node (host).
+ NODE_LOCAL,
+ /// Name lookup is local to the (sub)network.
+ NET_LOCAL
+ };
+
+ // = Initialization and termination methods.
+ /// "Do-nothing" constructor.
+ ACE_Naming_Context (void);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace. Note that <light>
+ * specifies whether or not we want to use
+ * ACE_Lite_MMap_Memory_Pool. By default we use ACE_MMap_Memory_Pool.
+ */
+ ACE_Naming_Context (Context_Scope_Type scope_in, int light = 0);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace. Note that <light>
+ * specifies whether or not we want to use
+ * ACE_Lite_MMap_Memory_Pool. By default we use ACE_MMap_Memory_Pool.
+ */
+ int open (Context_Scope_Type scope_in = ACE_Naming_Context::PROC_LOCAL,
+ int light = 0);
+
+ /// Deletes the instance of Name Space. Must be called before
+ /// switching name spaces.
+ int close (void);
+
+ /// Release all resources. Gets called by destructor and fini.
+ int close_down (void);
+
+ /// destructor, do some cleanup :TBD: last dtor should "compress"
+ /// file
+ ~ACE_Naming_Context (void);
+
+ // = Dynamic initialization hooks.
+ /// Initialize name options and naming context when dynamically
+ /// linked.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ /// Close down the test when dynamically unlinked.
+ virtual int fini (void);
+
+ /// Returns information about this context.
+ virtual int info (ACE_TCHAR **strp, size_t length) const;
+
+ /// Returns the ACE_Name_Options associated with the Naming_Context
+ ACE_Name_Options *name_options (void);
+
+ /// Bind a new name to a naming context (Wide character strings).
+ int bind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /// Bind a new name to a naming context ( character strings).
+ int bind (const char *name_in,
+ const char *value_in,
+ const char *type_in = "");
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Naming_Context or bind a new name to the context, if it
+ * didn't exist yet. (Wide charcter strings interface).
+ */
+ int rebind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Naming_Context or bind a new name to the context, if it
+ * didn't exist yet. ( charcter strings interface)
+ */
+ int rebind (const char *name_in,
+ const char *value_in,
+ const char *type_in = "");
+
+ /// Delete a name from a ACE_Naming_Context (Wide charcter strings
+ /// Interface).
+ int unbind (const ACE_NS_WString &name_in);
+
+ /// Delete a name from a ACE_Naming_Context (character strings
+ /// interface).
+ int unbind (const char *name_in);
+
+ /// Get value and type of a given name binding (Wide chars). The
+ /// caller is responsible for deleting both <value_out> and <type_out>!
+ int resolve (const ACE_NS_WString &name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out);
+
+ /**
+ * Get value and type of a given name binding (Wide chars output).
+ * The caller is responsible for deleting both <value_out> and
+ * <type_out>!
+ */
+ int resolve (const char *name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out);
+
+ /// Get value and type of a given name binding ( chars ). The caller
+ /// is responsible for deleting both <value_out> and <type_out>!
+ int resolve (const char *name_in,
+ char *&value_out,
+ char *&type_out);
+
+ /// Get a set of names matching a specified pattern (wchars). Matching
+ /// means the names must begin with the pattern string.
+ int list_names (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of names matching a specified pattern (chars). Matching
+ /// means the names must begin with the pattern string.
+ int list_names (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in);
+
+ /// Get a set of values matching a specified pattern (wchars). Matching
+ /// means the values must begin with the pattern string.
+ int list_values (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of values matching a specified pattern (chars). Matching
+ /// means the values must begin with the pattern string.
+ int list_values (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in);
+
+ /// Get a set of types matching a specified pattern (wchars). Matching
+ /// means the types must begin with the pattern string.
+ int list_types (ACE_PWSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of types matching a specified pattern (chars). Matching
+ /// means the types must begin with the pattern string.
+ int list_types (ACE_PWSTRING_SET &set_out,
+ const char *pattern_in);
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_name_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_name_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in);
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_value_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_value_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in);
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_type_entries (ACE_BINDING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_type_entries (ACE_BINDING_SET &set_out,
+ const char *pattern_in);
+
+ /// Dump the state of the object.
+ void dump (void);
+
+private:
+ /// Keep track of the options such as database name etc per Naming Context
+ ACE_Name_Options *name_options_;
+
+ /// Name space (can be either local or remote) dynamically bound.
+ ACE_Name_Space *name_space_;
+
+ /// Holds the local hostname.
+ ACE_TCHAR hostname_[MAXHOSTNAMELEN + 1];
+
+ /// Holds name of net name server.
+ const ACE_TCHAR *netnameserver_host_;
+
+ /// Holds port number of the net name server.
+ int netnameserver_port_;
+
+ /// 1 if we're on the same local machine as the name server, else 0.
+ int local (void);
+
+};
+
+/**
+ * @class ACE_Name_Options
+ *
+ * @brief Manages the options for the ACE Name_Server.
+ */
+class ACE_Export ACE_Name_Options
+{
+public:
+ // = Initialization and termination methods.
+ ACE_Name_Options (void);
+ ~ACE_Name_Options (void);
+
+ /// Parse arguments.
+ void parse_args (int argc,
+ ACE_TCHAR *argv[]);
+
+ // = Set/Get port number
+ void nameserver_port (int port);
+ int nameserver_port (void);
+
+ // = Set/Get the context
+ ACE_Naming_Context::Context_Scope_Type context (void);
+ void context (ACE_Naming_Context::Context_Scope_Type);
+
+ // = Set/Get host name
+ void nameserver_host (const ACE_TCHAR *host);
+ const ACE_TCHAR *nameserver_host (void);
+
+ // = Set/Get name space directory
+ void namespace_dir (const ACE_TCHAR *dir);
+ const ACE_TCHAR *namespace_dir (void);
+
+ // = Set/Get process name
+ void process_name (const ACE_TCHAR *dir);
+ const ACE_TCHAR *process_name (void);
+
+ // = Set/Get database name
+ void database (const ACE_TCHAR *);
+ const ACE_TCHAR *database (void);
+
+ // = Set/Get base address of the underlying allocator
+ void base_address (char *address);
+ char *base_address (void);
+
+ // Set/Get use of registry in naming
+ int use_registry (void);
+ void use_registry (int);
+
+ /// Return debug status
+ int debug (void);
+
+ /// Return verbose status
+ int verbose (void);
+
+private:
+ /// Extra debugging info
+ int debugging_;
+
+ /// Extra verbose messages
+ int verbosity_;
+
+ /// Use Win32 Registry
+ int use_registry_;
+
+ /// Port to connect to nameserver process.
+ int nameserver_port_;
+
+ /// Hostname of nameserver.
+ const ACE_TCHAR *nameserver_host_;
+
+ /// Directory to hold name_bindings.
+ ACE_TCHAR *namespace_dir_;
+
+ /// Name of this process.
+ const ACE_TCHAR *process_name_;
+
+ /// Name of the database that stores the name/value/type bindings.
+ const ACE_TCHAR *database_;
+
+ /// Base address of the underlying allocator
+ char *base_address_;
+
+ /// The context in which the naming database will be created.
+ ACE_Naming_Context::Context_Scope_Type context_;
+};
+
+ACE_FACTORY_DECLARE (ACE, ACE_Naming_Context)
+ACE_STATIC_SVC_DECLARE_EXPORT (ACE,ACE_Naming_Context)
+
+#include "ace/post.h"
+#endif /* ACE_NAMING_CONTEXT_H */
diff --git a/ace/Other/Registry_Name_Space.cpp b/ace/Other/Registry_Name_Space.cpp
new file mode 100644
index 00000000000..276f875657b
--- /dev/null
+++ b/ace/Other/Registry_Name_Space.cpp
@@ -0,0 +1,277 @@
+// $Id$
+
+#include "ace/Registry_Name_Space.h"
+
+ACE_RCSID(ace, Registry_Name_Space, "$Id$")
+
+#if (defined (ACE_WIN32) && defined (UNICODE))
+// This only works on Win32 platforms when UNICODE is turned on
+
+ACE_Registry_Name_Space::ACE_Registry_Name_Space (void)
+{
+}
+
+ACE_Registry_Name_Space::ACE_Registry_Name_Space (ACE_Name_Options *name_options)
+{
+ if (this->open (name_options) != 0)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Registry_Name_Space::open")));
+}
+
+
+ACE_Registry_Name_Space::~ACE_Registry_Name_Space (void)
+{
+}
+
+
+int
+ACE_Registry_Name_Space::open (ACE_Name_Options *name_options)
+{
+ const ACE_TCHAR *host = name_options->nameserver_host ();
+ ACE_Registry::Naming_Context predefined;
+
+ int result = ACE_Predefined_Naming_Contexts::connect (predefined,
+ HKEY_LOCAL_MACHINE,
+ host);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Predefined_Naming_Context::connect")),
+ result);
+ else
+ {
+ // Directory
+ ACE_TString name = name_options->namespace_dir ();
+ // Separator
+ name += ACE_Registry::STRING_SEPARATOR;
+ // Filename
+ name += name_options->database ();
+
+ // Create new context or bind to existing one
+ result = predefined.bind_context (name,
+ this->context_);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_Registry::Naming_Context::bind_context")), result);
+ }
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ // Pointer to data
+ const ACE_USHORT16 *data = value.fast_rep ();
+
+ // Size
+ u_long size = value.length () * sizeof (ACE_USHORT16);
+
+ // Represent value as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) data,
+ size,
+ REG_SZ);
+ // Add new <key>/<value> pair
+#if defined ACE_USES_WCHAR
+ return this->context_.bind (name.fast_rep(),
+ object);
+#else
+ return this->context_.bind (name.char_rep(),
+ object);
+#endif /* ACE_HAS_WCHAR */
+}
+
+
+int
+ACE_Registry_Name_Space::rebind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ // Pointer to data
+ const ACE_USHORT16 *data = value.fast_rep ();
+
+ // Size
+ u_long size = value.length () * sizeof (ACE_USHORT16);
+
+ // Represent value as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) data,
+ size,
+ REG_SZ);
+ // Add new <key>/<value> pair
+#if defined (ACE_USES_WCHAR)
+ return this->context_.rebind (name.fast_rep (),
+ object);
+#else
+ return this->context_.rebind (name.char_rep (),
+ object);
+#endif /* ACE_USES_WCHAR */
+}
+
+
+int
+ACE_Registry_Name_Space::unbind (const ACE_NS_WString &name)
+{
+#if defined (ACE_USES_WCHAR)
+ return this->context_.unbind (name.fast_rep ());
+#else
+ return this->context_.unbind (name.char_rep ());
+#endif /* ACE_USES_WCHAR */
+}
+
+
+int
+ACE_Registry_Name_Space::resolve (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type)
+{
+ // This object will be used to query the size of the data.
+ // Note: The query_object.data will be null for this invocation.
+ ACE_Registry::Object query_object;
+ int result =
+#if defined (ACE_USES_WCHAR)
+ this->context_.resolve (name.fast_rep (), query_object);
+#else
+ this->context_.resolve (name.char_rep (), query_object);
+#endif /* ACE_USES_WCHAR */
+ if (result != 0)
+ return result;
+
+ // Resize the value passed by the user
+ // Note: -1 is used because the size includes the null terminator
+ value.resize ((query_object.size () - 1) / sizeof (ACE_USHORT16));
+
+ // Represent new space as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) value.fast_rep (),
+ query_object.size (),
+ REG_SZ);
+
+#if defined (ACE_USES_WCHAR)
+ result = this->context_.resolve (name.fast_rep (), object);
+#else
+ result = this->context_.resolve (name.char_rep (), object);
+#endif /* ACE_USES_WCHAR */
+ if (object.size () != query_object.size ())
+ return -1;
+ if (result != 0)
+ return result;
+
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space:: list_names (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_BINDING_SET binding_set;
+ int result = this->list_name_entries (binding_set,
+ pattern);
+ if (result != 0)
+ return result;
+
+ ACE_BINDING_ITERATOR iterator (binding_set);
+
+ for (ACE_Name_Binding *entry = 0;
+ iterator.next (entry) !=0;
+ iterator.advance())
+ {
+ set.insert (entry->name_);
+ }
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::list_values (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_BINDING_SET binding_set;
+ int result = this->list_name_entries (binding_set,
+ pattern);
+ if (result != 0)
+ return result;
+
+ ACE_BINDING_ITERATOR iterator (binding_set);
+
+ for (ACE_Name_Binding *entry = 0;
+ iterator.next (entry) !=0;
+ iterator.advance())
+ {
+ set.insert (entry->value_);
+ }
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::list_types (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_Registry::Binding_List list;
+ int result = this->context_.list (list);
+ if (result != 0)
+ return result;
+
+ // Iterator through all entries
+ for (ACE_Registry::Binding_List::iterator i = list.begin ();
+ i != list.end ();
+ i++)
+ {
+ // Yeeesss! STL rules!
+ ACE_Registry::Binding &binding = *i;
+
+ if (binding.type () == ACE_Registry::OBJECT)
+ {
+ // Key
+ ACE_TString string = binding.name ();
+ ACE_NS_WString key (string.c_str ());
+
+ // Value
+ ACE_NS_WString value;
+ char *type = 0;
+ result = this->resolve (key,
+ value,
+ type);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_Registry::Naming_Context::resolve")), result);
+
+ // Complete binding
+ ACE_Name_Binding binding (key, value, type);
+ set.insert (binding);
+ }
+ }
+ return 0;
+}
+
+
+int
+ACE_Registry_Name_Space::list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ return this->list_name_entries (set, pattern);
+}
+
+
+int
+ACE_Registry_Name_Space::list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ return this->list_name_entries (set, pattern);
+}
+
+
+void
+ACE_Registry_Name_Space::dump (void) const
+{
+}
+
+
+#endif /* ACE_WIN32 && UNICODE */
diff --git a/ace/Other/Registry_Name_Space.h b/ace/Other/Registry_Name_Space.h
new file mode 100644
index 00000000000..075c2643f56
--- /dev/null
+++ b/ace/Other/Registry_Name_Space.h
@@ -0,0 +1,134 @@
+/*-*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Registry_Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyarali (irfan@cs.wustl.edu)
+ */
+//=============================================================================
+
+
+#ifndef ACE_REGISTRY_NAME_SPACE_H
+#define ACE_REGISTRY_NAME_SPACE_H
+#include "ace/pre.h"
+
+#include "ace/OS.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if (defined (ACE_WIN32) && defined (UNICODE))
+// This only works on Win32 platforms when UNICODE is turned on
+
+#include "ace/Registry.h"
+#include "ace/Naming_Context.h"
+#include "ace/Name_Space.h"
+
+/**
+ * @class ACE_Registry_Name_Space
+ *
+ * @brief Interface to a Name Server Database which is maintained by
+ * the Win32 Registry. Allows to add, change, remove and
+ * resolve NameBindings.
+ *
+ * Manages a Naming Service for a registry name space which
+ * includes bindings for all contexts. All strings are stored in
+ * wide character format. A Name Binding consists of a name
+ * (that's the key), a value string. There is no type string
+ * support in this Name Space.
+ */
+class ACE_Export ACE_Registry_Name_Space : public ACE_Name_Space
+{
+public:
+
+ /// Constructor
+ ACE_Registry_Name_Space (void);
+
+ /// Contacts and opens the registry on the specified server
+ ACE_Registry_Name_Space (ACE_Name_Options *name_options);
+
+ /// Destructor
+ ~ACE_Registry_Name_Space (void);
+
+ /// Contacts and opens the registry on the specified server
+ int open (ACE_Name_Options *name_options);
+
+ /// Bind a new name to a naming context (Wide character strings).
+ int bind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Name_Space or bind a new name to the context, if it didn't
+ * exist yet. (Wide charcter strings interface).
+ */
+ int rebind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /// Delete a name from a ACE_Name_Space (Wide charcter strings
+ /// Interface).
+ int unbind (const ACE_NS_WString &name_in);
+
+ /// Get value and type of a given name binding (Wide chars). The
+ /// caller is responsible for deleting both <value_out> and <type_out>!
+ int resolve (const ACE_NS_WString &name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out);
+
+ /// Get a set of names matching a specified pattern (wchars). Matching
+ /// means the names must begin with the pattern string.
+ int list_names (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of values matching a specified pattern (wchars). Matching
+ /// means the values must begin with the pattern string.
+ int list_values (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of types matching a specified pattern (wchars). Matching
+ /// means the types must begin with the pattern string.
+ int list_types (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ int list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ int list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ int list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /// Dump the state of the object
+ void dump (void) const;
+
+private:
+
+ /// current context
+ ACE_Registry::Naming_Context context_;
+};
+
+#endif /* ACE_WIN32 && UNICODE */
+#include "ace/post.h"
+#endif /* ACE_REGISTRY_NAME_SPACE_H */
diff --git a/ace/Other/Remote_Name_Space.cpp b/ace/Other/Remote_Name_Space.cpp
new file mode 100644
index 00000000000..bc906f917a5
--- /dev/null
+++ b/ace/Other/Remote_Name_Space.cpp
@@ -0,0 +1,351 @@
+// Remote_Name_Space.cpp
+// $Id$
+
+#include "ace/Remote_Name_Space.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, Remote_Name_Space, "$Id$")
+
+int
+ACE_Remote_Name_Space::open (const ACE_TCHAR *servername, u_short port)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::open");
+ ACE_INET_Addr servaddr;
+
+ // Initialize Addr
+ if (servaddr.set (port, servername) == -1)
+ return -1;
+
+ // Connect to Name Server process.
+ if (this->ns_proxy_.open (servaddr) == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_Remote_Name_Space::ACE_Remote_Name_Space (void)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::ACE_Remote_Name_Space");
+}
+
+ACE_Remote_Name_Space::ACE_Remote_Name_Space (const ACE_TCHAR *hostname,
+ u_short port)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::ACE_Remote_Name_Space");
+ if (this->open (hostname, port) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_Remote_Name_Space::ACE_Remote_Name_Space")));
+}
+
+int
+ACE_Remote_Name_Space::bind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::bind");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> name_urep (name.ushort_rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> value_urep (value.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::BIND,
+ name_urep.get (),
+ name.length () * sizeof (ACE_USHORT16),
+ value_urep.get (),
+ value.length () * sizeof (ACE_USHORT16),
+ type,
+ ACE_OS::strlen (type));
+ return this->ns_proxy_.request_reply (request);
+}
+
+int
+ACE_Remote_Name_Space::rebind (const ACE_NS_WString &name,
+ const ACE_NS_WString &value,
+ const char *type)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::rebind");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> name_urep (name.ushort_rep ());
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> value_urep (value.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::REBIND,
+ name_urep.get (),
+ name.length () * sizeof (ACE_USHORT16),
+ value_urep.get (),
+ value.length () * sizeof (ACE_USHORT16),
+ type,
+ ACE_OS::strlen (type));
+ return this->ns_proxy_.request_reply (request);
+}
+
+int
+ACE_Remote_Name_Space::resolve (const ACE_NS_WString &name,
+ ACE_NS_WString &value,
+ char *&type)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::resolve");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> name_urep (name.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::RESOLVE,
+ name_urep.get (),
+ name.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply;
+
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ return -1;
+
+ ACE_NS_WString temp (reply.value (), reply.value_len () / sizeof (ACE_USHORT16));
+ value = temp;
+ ACE_NEW_RETURN (type,
+ char[reply.type_len () + 1],
+ -1);
+ ACE_OS::strcpy (type, reply.type ());
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::unbind (const ACE_NS_WString &name)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::unbind");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> name_urep (name.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::UNBIND,
+ name_urep.get (),
+ name.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+ return this->ns_proxy_.request_reply (request);
+}
+
+int
+ACE_Remote_Name_Space::list_names (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_names");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_NAMES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_names")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString name (reply.name (),
+ reply.name_len () / sizeof (ACE_USHORT16));
+ set.insert (name);
+ }
+ }
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::list_values (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_values");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_VALUES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_values")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_USHORT16));
+ set.insert (value);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::list_types (ACE_WSTRING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_types");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_TYPES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_values")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString type (reply.type ());
+ set.insert (type);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_name_entries");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_NAME_ENTRIES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_names")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString name (reply.name (),
+ reply.name_len () / sizeof (ACE_USHORT16));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_USHORT16));
+ ACE_Name_Binding entry (name,
+ value,
+ reply.type ());
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_value_entries");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_VALUE_ENTRIES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_values")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString name (reply.name (),
+ reply.name_len () / sizeof (ACE_USHORT16));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_USHORT16));
+ ACE_Name_Binding entry (name,
+ value,
+ reply.type());
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+ACE_Remote_Name_Space::list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::list_type_entries");
+ ACE_Auto_Basic_Array_Ptr<ACE_USHORT16> pattern_urep (pattern.ushort_rep ());
+ ACE_Name_Request request (ACE_Name_Request::LIST_TYPE_ENTRIES,
+ pattern_urep.get (),
+ pattern.length () * sizeof (ACE_USHORT16),
+ 0, 0, 0, 0);
+
+ if (this->ns_proxy_.send_request (request) == -1)
+ return -1;
+
+ ACE_Name_Request reply (0, 0, 0, 0, 0, 0, 0, 0);
+
+ while (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ if (this->ns_proxy_.recv_reply (reply) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Remote_Name_Space::list_values")),
+ -1);
+ if (reply.msg_type () != ACE_Name_Request::MAX_ENUM)
+ {
+ ACE_NS_WString name (reply.name (),
+ reply.name_len () / sizeof (ACE_USHORT16));
+ ACE_NS_WString value (reply.value (),
+ reply.value_len () / sizeof (ACE_USHORT16));
+ ACE_Name_Binding entry (name,
+ value,
+ reply.type ());
+ if (set.insert (entry) == -1)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ACE_Remote_Name_Space::~ACE_Remote_Name_Space (void)
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::~ACE_Remote_Name_Space");
+}
+
+void
+ACE_Remote_Name_Space::dump (void) const
+{
+ ACE_TRACE ("ACE_Remote_Name_Space::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->ns_proxy_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_Auto_Basic_Array_Ptr<ACE_USHORT16>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Auto_Basic_Array_Ptr<ACE_USHORT16>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/ace/Other/Remote_Name_Space.h b/ace/Other/Remote_Name_Space.h
new file mode 100644
index 00000000000..968278a74c5
--- /dev/null
+++ b/ace/Other/Remote_Name_Space.h
@@ -0,0 +1,140 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Remote_Name_Space.h
+ *
+ * $Id$
+ *
+ * @author Prashant Jain
+ */
+//=============================================================================
+
+
+#ifndef ACE_REMOTE_NAME_SPACE_H
+#define ACE_REMOTE_NAME_SPACE_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Name_Proxy.h"
+#include "ace/Name_Space.h"
+
+typedef ACE_Unbounded_Set<ACE_NS_WString> ACE_WSTRING_SET;
+
+/**
+ * @class ACE_Remote_Name_Space
+ *
+ * @brief Maintaining accesses Remote Name Server Database. Allows to
+ * add NameBindings, change them, remove them and resolve
+ * NameBindings.
+ *
+ * Manages a Naming Service for a remote name space which
+ * includes bindings for net_local naming context. All strings
+ * are stored in wide character format. A Name Binding consists
+ * of a name (that's the key), a value string and an optional
+ * type string (no wide chars).
+ */
+class ACE_Export ACE_Remote_Name_Space : public ACE_Name_Space
+{
+public:
+ // = Initialization and termination methods.
+ /// "Do-nothing" constructor.
+ ACE_Remote_Name_Space (void);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace.
+ */
+ ACE_Remote_Name_Space (const ACE_TCHAR *hostname, u_short port);
+
+ /**
+ * Specifies the scope of this namespace, opens and memory-maps the
+ * associated file (if accessible) or contacts the dedicated name
+ * server process for NET_LOCAL namespace.
+ */
+ int open (const ACE_TCHAR *servername, u_short port);
+
+ /// destructor, do some cleanup :TBD: last dtor should "compress"
+ /// file
+ ~ACE_Remote_Name_Space (void);
+
+ /// Bind a new name to a naming context (Wide character strings).
+ virtual int bind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /**
+ * Overwrite the value or type of an existing name in a
+ * ACE_Remote_Name_Space or bind a new name to the context, if it
+ * didn't exist yet. (Wide charcter strings interface).
+ */
+ virtual int rebind (const ACE_NS_WString &name_in,
+ const ACE_NS_WString &value_in,
+ const char *type_in = "");
+
+ /// Delete a name from a ACE_Remote_Name_Space (Wide charcter strings
+ /// Interface).
+ virtual int unbind (const ACE_NS_WString &name_in);
+
+ /// Get value and type of a given name binding (Wide chars). The
+ /// caller is responsible for deleting both <value_out> and <type_out>!
+ virtual int resolve (const ACE_NS_WString &name_in,
+ ACE_NS_WString &value_out,
+ char *&type_out);
+
+ /// Get a set of names matching a specified pattern (wchars). Matching
+ /// means the names must begin with the pattern string.
+ virtual int list_names (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of values matching a specified pattern (wchars). Matching
+ /// means the values must begin with the pattern string.
+ virtual int list_values (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /// Get a set of types matching a specified pattern (wchars). Matching
+ /// means the types must begin with the pattern string.
+ virtual int list_types (ACE_WSTRING_SET &set_out,
+ const ACE_NS_WString &pattern_in);
+
+ /**
+ * Get a set of names matching a specified pattern (wchars). Matching
+ * means the names must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_name_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of values matching a specified pattern (wchars). Matching
+ * means the values must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_value_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /**
+ * Get a set of types matching a specified pattern (wchars). Matching
+ * means the types must begin with the pattern string. Returns the
+ * complete binding associated each pattern match.
+ */
+ virtual int list_type_entries (ACE_BINDING_SET &set,
+ const ACE_NS_WString &pattern);
+
+ /// Dump the state of the object.
+ virtual void dump (void) const;
+
+private:
+ /// Interface to Name server process for NET_LOCAL namespace.
+ ACE_Name_Proxy ns_proxy_;
+};
+
+#include "ace/post.h"
+#endif /* ACE_REMOTE_NAME_SPACE_H */
diff --git a/ace/Other/TP_Reactor.cpp b/ace/Other/TP_Reactor.cpp
new file mode 100644
index 00000000000..e6b0d189f89
--- /dev/null
+++ b/ace/Other/TP_Reactor.cpp
@@ -0,0 +1,829 @@
+// $Id$
+
+
+#include "ace/TP_Reactor.h"
+#include "ace/Reactor.h"
+#include "ace/Thread.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/TP_Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(ace, TP_Reactor, "$Id$")
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_TP_Reactor)
+
+int
+ACE_TP_Token_Guard::grab_token (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_TP_Token_Guard::grab_token");
+
+ // The order of these events is very subtle, modify with care.
+
+ // Try to grab the lock. If someone if already there, don't wake
+ // them up, just queue up in the thread pool.
+ int result = 0;
+
+ if (max_wait_time)
+ {
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ tv += *max_wait_time;
+
+ ACE_MT (result = this->token_.acquire_read (&ACE_TP_Reactor::no_op_sleep_hook,
+ 0,
+ &tv));
+ }
+ else
+ {
+ ACE_MT (result = this->token_.acquire_read (&ACE_TP_Reactor::no_op_sleep_hook));
+ }
+
+ // Now that this thread owns the token let us make
+ // Check for timeouts and errors.
+ if (result == -1)
+ {
+ if (errno == ETIME)
+ return 0;
+ else
+ return -1;
+ }
+
+ // We got the token and so let us mark ourseleves as owner
+ this->owner_ = 1;
+
+ return result;
+}
+
+
+int
+ACE_TP_Token_Guard::acquire_token (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_TP_Token_Guard::acquire_token");
+
+ // Try to grab the lock. If someone if already there, don't wake
+ // them up, just queue up in the thread pool.
+ int result = 0;
+
+ if (max_wait_time)
+ {
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ tv += *max_wait_time;
+
+ ACE_MT (result = this->token_.acquire (0,
+ 0,
+ &tv));
+ }
+ else
+ {
+ ACE_MT (result = this->token_.acquire ());
+ }
+
+ // Now that this thread owns the token let us make
+ // Check for timeouts and errors.
+ if (result == -1)
+ {
+ if (errno == ETIME)
+ return 0;
+ else
+ return -1;
+ }
+
+ // We got the token and so let us mark ourseleves as owner
+ this->owner_ = 1;
+
+ return result;
+}
+
+
+
+ACE_TP_Reactor::ACE_TP_Reactor (ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int mask_signals)
+ : ACE_Select_Reactor (sh, tq, 0, 0, mask_signals)
+{
+ ACE_TRACE ("ACE_TP_Reactor::ACE_TP_Reactor");
+ this->supress_notify_renew (1);
+}
+
+ACE_TP_Reactor::ACE_TP_Reactor (size_t size,
+ int rs,
+ ACE_Sig_Handler *sh,
+ ACE_Timer_Queue *tq,
+ int mask_signals)
+ : ACE_Select_Reactor (size, rs, sh, tq, 0, 0, mask_signals)
+{
+ ACE_TRACE ("ACE_TP_Reactor::ACE_TP_Reactor");
+ this->supress_notify_renew (1);
+}
+
+int
+ACE_TP_Reactor::owner (ACE_thread_t, ACE_thread_t *o_id)
+{
+ ACE_TRACE ("ACE_TP_Reactor::owner");
+ if (o_id)
+ *o_id = ACE_Thread::self ();
+
+ return 0;
+}
+
+int
+ACE_TP_Reactor::owner (ACE_thread_t *t_id)
+{
+ ACE_TRACE ("ACE_TP_Reactor::owner");
+ *t_id = ACE_Thread::self ();
+
+ return 0;
+}
+
+int
+ACE_TP_Reactor::handle_events (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_TP_Reactor::handle_events");
+
+ // Stash the current time -- the destructor of this object will
+ // automatically compute how much time elpased since this method was
+ // called.
+ ACE_Countdown_Time countdown (max_wait_time);
+
+ // The order of these events is very subtle, modify with care.
+
+
+ // Instantiate the token guard which will try grabbing the token for
+ // this thread.
+ ACE_TP_Token_Guard guard (this->token_);
+
+
+ int result = guard.grab_token (max_wait_time);
+
+ // If the guard is NOT the owner just return the retval
+ if (!guard.is_owner ())
+ return result;
+
+ // After getting the lock just just for deactivation..
+ if (this->deactivated_)
+ return -1;
+
+ // Update the countdown to reflect time waiting for the token.
+ countdown.update ();
+
+
+ return this->dispatch_i (max_wait_time,
+ guard);
+}
+
+
+int
+ACE_TP_Reactor::remove_handler (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask)
+{
+ // Artificial scoping for grabbing and releasing the token
+ {
+ ACE_TP_Token_Guard guard (this->token_);
+
+ // Acquire the token
+ int result = guard.acquire_token ();
+
+ if (!guard.is_owner ())
+ return result;
+
+ // Call the remove_handler_i () with a DONT_CALL mask. We dont
+ // want to call the handle_close with the token held.
+ if (this->remove_handler_i (eh->get_handle (),
+ mask | ACE_Event_Handler::DONT_CALL) == -1)
+ return -1;
+ }
+
+ // Close down the <Event_Handler> unless we've been instructed not
+ // to.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)
+ eh->handle_close (ACE_INVALID_HANDLE, mask);
+
+ return 0;
+}
+
+int
+ACE_TP_Reactor::remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+
+ ACE_Event_Handler *eh = 0;
+
+ // Artificial scoping for grabbing and releasing the token
+ {
+ ACE_TP_Token_Guard guard (this->token_);
+
+ // Acquire the token
+ int result = guard.acquire_token ();
+
+ if (!guard.is_owner ())
+ return result;
+
+ size_t slot = 0;
+ eh = this->handler_rep_.find (handle, &slot);
+
+ if (eh == 0)
+ return -1;
+
+ // Call the remove_handler_i () with a DONT_CALL mask. We dont
+ // want to call the handle_close with the token held.
+ if (this->remove_handler_i (handle,
+ mask | ACE_Event_Handler::DONT_CALL) == -1)
+ return -1;
+ }
+
+ // Close down the <Event_Handler> unless we've been instructed not
+ // to.
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)
+ eh->handle_close (handle, mask);
+
+ return 0;
+}
+
+
+int
+ACE_TP_Reactor::remove_handler (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask m)
+{
+ // Array of <Event_Handlers> corresponding to <handles>
+ ACE_Event_Handler **aeh = 0;
+
+ // Allocate memory for the size of the handle set
+ ACE_NEW_RETURN (aeh,
+ ACE_Event_Handler *[handles.num_set ()],
+ -1);
+
+ size_t index = 0;
+
+ // Artificial scoping for grabbing and releasing the token
+ {
+ ACE_TP_Token_Guard guard (this->token_);
+
+ // Acquire the token
+ int result = guard.acquire_token ();
+
+ if (!guard.is_owner ())
+ return result;
+
+ ACE_HANDLE h;
+
+ ACE_Handle_Set_Iterator handle_iter (handles);
+
+ while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
+ {
+ size_t slot = 0;
+ ACE_Event_Handler *eh =
+ this->handler_rep_.find (h, &slot);
+
+ if (this->remove_handler_i (h,
+ m | ACE_Event_Handler::DONT_CALL) == -1)
+ {
+ delete [] aeh;
+ return -1;
+ }
+
+ aeh [index] = eh;
+ index ++;
+ }
+ }
+
+ // Close down the <Event_Handler> unless we've been instructed not
+ // to.
+ if (ACE_BIT_ENABLED (m, ACE_Event_Handler::DONT_CALL) == 0)
+ {
+ for (size_t i = 0; i < index; i++)
+ aeh[i]->handle_close (ACE_INVALID_HANDLE, m);
+ }
+
+ delete [] aeh;
+ return 0;
+}
+
+int
+ACE_TP_Reactor::remove_handler (int /*signum*/,
+ ACE_Sig_Action * /*new_disp*/,
+ ACE_Sig_Action * /*old_disp*/,
+ int /*sigkey*/)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+int
+ACE_TP_Reactor::remove_handler (const ACE_Sig_Set & /*sigset*/)
+{
+ ACE_NOTSUP_RETURN (-1);
+}
+
+
+int
+ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time,
+ ACE_TP_Token_Guard &guard)
+{
+ int event_count =
+ this->get_event_for_dispatching (max_wait_time);
+
+ int result = 0;
+
+ // Note: We are passing the <event_count> around, to have record of
+ // how many events still need processing. May be this could be
+ // useful in future.
+
+ // Dispatch signals
+ if (event_count == -1)
+ {
+ // Looks like we dont do any upcalls in dispatch signals. If at
+ // a later point of time, we decide to handle signals we have to
+ // release the lock before we make any upcalls.. What is here
+ // now is not the right thing...
+ // @@ We need to do better..
+ return this->handle_signals (event_count,
+ guard);
+ }
+
+ // If there are no signals and if we had received a proper
+ // event_count then first look at dispatching timeouts. We need to
+ // handle timers early since they may have higher latency
+ // constraints than I/O handlers. Ideally, the order of
+ // dispatching should be a strategy...
+
+ // NOTE: The event count does not have the number of timers that
+ // needs dispatching. But we are still passing this along. We dont
+ // need to do that. In the future we *may* have the timers also
+ // returned through the <event_count>. Just passing that along for
+ // that day.
+ result = this->handle_timer_events (event_count,
+ guard);
+
+ if (result > 0)
+ return result;
+
+
+ // Else justgo ahead fall through for further handling
+
+ if (event_count > 0)
+ {
+ // Next dispatch the notification handlers (if there are any to
+ // dispatch). These are required to handle multiple-threads that
+ // are trying to update the <Reactor>.
+ result = this->handle_notify_events (event_count,
+ guard);
+
+ if (result > 0)
+ return result;
+
+ // Else just fall through for further handling
+ }
+
+ if (event_count > 0)
+ {
+ // Handle socket events
+ return this->handle_socket_events (event_count,
+ guard);
+ }
+
+ return 0;
+
+}
+
+
+
+
+int
+ACE_TP_Reactor::handle_signals (int & /*event_count*/,
+ ACE_TP_Token_Guard & /*guard*/)
+{
+ ACE_TRACE ("ACE_TP_Reactor::handle_signals");
+
+ /*
+ *
+ * THIS METHOD SEEMS BROKEN
+ *
+ *
+ */
+ // First check for interrupts.
+ // Bail out -- we got here since <select> was interrupted.
+ if (ACE_Sig_Handler::sig_pending () != 0)
+ {
+ ACE_Sig_Handler::sig_pending (0);
+
+ // This piece of code comes from the old TP_Reactor. We did not
+ // handle signals at all then. If we happen to handle signals
+ // in the TP_Reactor, we should then start worryiung about this
+ // - Bala 21-Aug- 01
+#if 0
+ // Not sure if this should be done in the TP_Reactor
+ // case... leave it out for now. -Steve Huston 22-Aug-00
+
+ // If any HANDLES in the <ready_set_> are activated as a
+ // result of signals they should be dispatched since
+ // they may be time critical...
+ active_handle_count = this->any_ready (dispatch_set);
+ #else
+ // active_handle_count = 0;
+#endif
+
+ // Record the fact that the Reactor has dispatched a
+ // handle_signal() method. We need this to return the
+ // appropriate count.
+ return 1;
+ }
+
+ return -1;
+}
+
+
+int
+ACE_TP_Reactor::handle_timer_events (int & /*event_count*/,
+ ACE_TP_Token_Guard &guard)
+{
+ // Get the current time
+ ACE_Time_Value cur_time (this->timer_queue_->gettimeofday () +
+ this->timer_queue_->timer_skew ());
+
+ // Look for a node in the timer queue whose timer <= the present
+ // time.
+ ACE_Timer_Node_Dispatch_Info info;
+
+ if (this->timer_queue_->dispatch_info (cur_time,
+ info))
+ {
+ // Release the token before dispatching notifies...
+ guard.release_token ();
+
+ // call the functor
+ this->timer_queue_->upcall (info.type_,
+ info.act_,
+ cur_time);
+
+ // We have dispatched a timer
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+int
+ACE_TP_Reactor::handle_notify_events (int & /*event_count*/,
+ ACE_TP_Token_Guard &guard)
+{
+ // Get the handle on which notify calls could have occured
+ ACE_HANDLE notify_handle =
+ this->get_notify_handle ();
+
+ int result = 0;
+
+ // The notify was not in the list returned by
+ // wait_for_multiple_events ().
+ if (notify_handle == ACE_INVALID_HANDLE)
+ return result;
+
+ // Now just do a read on the pipe..
+ ACE_Notification_Buffer buffer;
+
+ // Clear the handle of the read_mask of our <ready_set_>
+ this->ready_set_.rd_mask_.clr_bit (notify_handle);
+
+ // Keep reading notifies till we empty it or till we have a
+ // dispatchable buffer
+ while (this->notify_handler_->read_notify_pipe (notify_handle,
+ buffer) > 0)
+ {
+ // Just figure out whether we can read any buffer that has
+ // dispatchable info. If not we have just been unblocked by
+ // another thread trying to update the reactor. If we get any
+ // buffer that needs dispatching we will dispatch that after
+ // releasing the lock
+ if (this->notify_handler_->is_dispatchable (buffer) > 0)
+ {
+ // Release the token before dispatching notifies...
+ guard.release_token ();
+
+ // Dispatch the upcall for the notify
+ this->notify_handler_->dispatch_notify (buffer);
+
+ // We had a successful dispatch.
+ result = 1;
+
+ // break out of the while loop
+ break;
+ }
+ }
+
+ // If we did ssome work, then we just return 1 which will allow us
+ // to get out of here. If we return 0, then we will be asked to do
+ // some work ie. dispacth socket events
+ return result;
+}
+
+int
+ACE_TP_Reactor::handle_socket_events (int &event_count,
+ ACE_TP_Token_Guard &guard)
+{
+
+ // We got the lock, lets handle some events. Note: this method will
+ // *not* dispatch any I/O handlers. It will dispatch signals,
+ // timeouts, and notifications.
+ ACE_EH_Dispatch_Info dispatch_info;
+
+ this->get_socket_event_info (dispatch_info);
+
+ // If there is any event handler that is ready to be dispatched, the
+ // dispatch information is recorded in dispatch_info.
+ if (dispatch_info.dispatch ())
+ {
+ // Suspend the handler so that other threads don't start
+ // dispatching it.
+ // NOTE: This check was performed in older versions of the
+ // TP_Reactor. Looks like it is a waste..
+ if (dispatch_info.event_handler_ != this->notify_handler_)
+ this->suspend_i (dispatch_info.handle_);
+ }
+
+ // Release the lock. Others threads can start waiting.
+ guard.release_token ();
+
+ int result = 0;
+
+ // If there was an event handler ready, dispatch it.
+ if (dispatch_info.dispatch ())
+ {
+ /// Decrement the event left
+ --event_count;
+
+ if (this->dispatch_socket_event (dispatch_info) == 0)
+ ++result; // Dispatched an event
+
+ int flag = 0;
+
+ // Hack of the decade ;-). We make an extra check for the handle
+ // in addition to the event handler before we make a check for
+ // the resume_handler ().
+ if (dispatch_info.event_handler_ != 0 &&
+ this->handler_rep_.find (dispatch_info.handle_) != 0)
+ {
+ flag =
+ dispatch_info.event_handler_->resume_handler ();
+ }
+
+ if (dispatch_info.handle_ != ACE_INVALID_HANDLE &&
+ dispatch_info.event_handler_ != this->notify_handler_ &&
+ flag == 0)
+ this->resume_handler (dispatch_info.handle_);
+ }
+
+ return result;
+}
+
+int
+ACE_TP_Reactor::mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ ACE_TRACE ("ACE_TP_Reactor::mask_ops");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token,
+ ace_mon, this->token_, -1));
+
+ int result = 0;
+
+ // If it looks like the handle isn't suspended, then
+ // set the ops on the wait_set_, otherwise set the suspend_set_.
+
+ if (this->suspend_set_.rd_mask_.is_set (handle) == 0
+ && this->suspend_set_.wr_mask_.is_set (handle) == 0
+ && this->suspend_set_.ex_mask_.is_set (handle) == 0)
+
+ result = this->bit_ops (handle, mask,
+ this->wait_set_,
+ ops);
+ else
+
+ result = this->bit_ops (handle, mask,
+ this->suspend_set_,
+ ops);
+
+ return result;
+}
+
+
+
+int
+ACE_TP_Reactor::get_event_for_dispatching (ACE_Time_Value *max_wait_time)
+{
+
+ // If the reactor handler state has changed, clear any remembered
+ // ready bits and re-scan from the master wait_set.
+ if (this->state_changed_)
+ {
+ this->ready_set_.rd_mask_.reset ();
+ this->ready_set_.wr_mask_.reset ();
+ this->ready_set_.ex_mask_.reset ();
+ this->state_changed_ = 0;
+ }
+ else
+ {
+ // This is a hack... somewhere, under certain conditions (which
+ // I don't understand...) the mask will have all of its bits clear,
+ // yet have a size_ > 0. This is an attempt to remedy the affect,
+ // without knowing why it happens.
+
+ //# if !(defined (__SUNPRO_CC) && (__SUNPRO_CC > 0x500))
+ // SunCC seems to be having problems with this piece of code
+ // here. I am not sure why though. This works fine with other
+ // compilers. As we dont seem to understand when this piece of
+ // code is needed and as it creates problems for SunCC we will
+ // not compile this. Most of the tests in TAO seem to be happy
+ // without this in SunCC.
+ this->ready_set_.rd_mask_.sync (this->ready_set_.rd_mask_.max_set ());
+ this->ready_set_.wr_mask_.sync (this->ready_set_.wr_mask_.max_set ());
+ this->ready_set_.ex_mask_.sync (this->ready_set_.ex_mask_.max_set ());
+ //# endif /* ! __SUNPRO_CC */
+
+ }
+
+ return this->wait_for_multiple_events (this->ready_set_,
+ max_wait_time);
+}
+
+int
+ACE_TP_Reactor::get_socket_event_info (ACE_EH_Dispatch_Info &event)
+{
+ event.reset (); // Nothing to dispatch yet
+
+ // Check for dispatch in write, except, read. Only catch one, but if
+ // one is caught, be sure to clear the handle from each mask in case
+ // there is more than one mask set for it. This would cause problems
+ // if the handler is suspended for dispatching, but its set bit in
+ // another part of ready_set_ kept it from being dispatched.
+ int found_io = 0;
+ ACE_HANDLE handle;
+
+ // @@todo: We can do quite a bit of code reduction here. Let me get
+ // it to work before I do this.
+ {
+ ACE_Handle_Set_Iterator handle_iter (this->ready_set_.wr_mask_);
+
+ while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
+ {
+ if (this->is_suspended_i (handle))
+ continue;
+
+ // Remember this info
+ event.set (handle,
+ this->handler_rep_.find (handle),
+ ACE_Event_Handler::WRITE_MASK,
+ &ACE_Event_Handler::handle_output);
+ this->ready_set_.wr_mask_.clr_bit (handle);
+ this->ready_set_.ex_mask_.clr_bit (handle);
+ this->ready_set_.rd_mask_.clr_bit (handle);
+ found_io = 1;
+ }
+ }
+
+ if (!found_io)
+ {
+ ACE_Handle_Set_Iterator handle_iter (this->ready_set_.ex_mask_);
+
+ while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
+ {
+ if (this->is_suspended_i (handle))
+ continue;
+
+ // Remember this info
+ event.set (handle,
+ this->handler_rep_.find (handle),
+ ACE_Event_Handler::EXCEPT_MASK,
+ &ACE_Event_Handler::handle_exception);
+ this->ready_set_.ex_mask_.clr_bit (handle);
+ this->ready_set_.wr_mask_.clr_bit (handle);
+ this->ready_set_.rd_mask_.clr_bit (handle);
+ found_io = 1;
+ }
+ }
+
+ if (!found_io)
+ {
+ ACE_Handle_Set_Iterator handle_iter (this->ready_set_.rd_mask_);
+
+ while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
+ {
+ if (this->is_suspended_i (handle))
+ continue;
+
+ // Remember this info
+ event.set (handle,
+ this->handler_rep_.find (handle),
+ ACE_Event_Handler::READ_MASK,
+ &ACE_Event_Handler::handle_input);
+ this->ready_set_.rd_mask_.clr_bit (handle);
+ this->ready_set_.wr_mask_.clr_bit (handle);
+ this->ready_set_.ex_mask_.clr_bit (handle);
+ found_io = 1;
+ }
+ }
+
+ return found_io;
+}
+
+
+
+// Dispatches a single event handler
+int
+ACE_TP_Reactor::dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info)
+{
+ ACE_TRACE ("ACE_TP_Reactor::dispatch_socket_event");
+
+ ACE_HANDLE handle = dispatch_info.handle_;
+ ACE_Event_Handler *event_handler = dispatch_info.event_handler_;
+ ACE_Reactor_Mask mask = dispatch_info.mask_;
+ ACE_EH_PTMF callback = dispatch_info.callback_;
+
+ // Check for removed handlers.
+ if (event_handler == 0)
+ return -1;
+
+ // Upcall. If the handler returns positive value (requesting a
+ // reactor callback) don't set the ready-bit because it will be
+ // ignored if the reactor state has changed. Just call back
+ // as many times as the handler requests it. Other threads are off
+ // handling other things.
+ int status = 1;
+ while (status > 0)
+ status = (event_handler->*callback) (handle);
+
+ // If negative, remove from Reactor
+ if (status < 0)
+ {
+ int retval =
+ this->remove_handler (handle, mask);
+
+ // As the handler is no longer valid, invalidate the handle
+ dispatch_info.event_handler_ = 0;
+ dispatch_info.handle_ = ACE_INVALID_HANDLE;
+
+ return retval;
+ }
+
+ // assert (status >= 0);
+ return 0;
+}
+
+int
+ACE_TP_Reactor::resumable_handler (void)
+{
+ return 1;
+}
+
+int
+ACE_TP_Reactor::handle_events (ACE_Time_Value &max_wait_time)
+{
+ return ACE_Select_Reactor::handle_events (&max_wait_time);
+}
+
+int
+ACE_TP_Reactor::mask_ops (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ int ops)
+{
+ return this->mask_ops (eh->get_handle (), mask, ops);
+}
+
+void
+ACE_TP_Reactor::notify_handle (ACE_HANDLE,
+ ACE_Reactor_Mask,
+ ACE_Handle_Set &,
+ ACE_Event_Handler *,
+ ACE_EH_PTMF)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_TP_Reactor::notify_handle: Wrong version of notify_handle() gets called")));
+}
+
+ACE_HANDLE
+ACE_TP_Reactor::get_notify_handle (void)
+{
+ // Call the notify handler to get a handle on which we would have a
+ // notify waiting
+ ACE_HANDLE read_handle =
+ this->notify_handler_->notify_handle ();
+
+ // Check whether the rd_mask has been set on that handle. If so
+ // return the handle.
+ // if (read_handle != ACE_INVALID_HANDLE &&
+ //this->ready_set_.rd_mask_.is_set (read_handle))
+ if (read_handle != ACE_INVALID_HANDLE)
+ {
+ ACE_Handle_Set_Iterator handle_iter (this->ready_set_.rd_mask_);
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+
+ while ((handle = handle_iter ()) == read_handle)
+ {
+ return read_handle;
+ }
+ ACE_UNUSED_ARG (handle);
+ }
+
+ // None found..
+ return ACE_INVALID_HANDLE;
+}
diff --git a/ace/Other/TP_Reactor.h b/ace/Other/TP_Reactor.h
new file mode 100644
index 00000000000..e51abd99db9
--- /dev/null
+++ b/ace/Other/TP_Reactor.h
@@ -0,0 +1,357 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file TP_Reactor.h
+ *
+ * $Id$
+ *
+ * The <ACE_TP_Reactor> (aka, Thread Pool Reactor) uses the
+ * Leader/Followers pattern to demultiplex events among a pool of
+ * threads. When using a thread pool reactor, an application
+ * pre-spawns a _fixed_ number of threads. When these threads
+ * invoke the <ACE_TP_Reactor>'s <handle_events> method, one thread
+ * will become the leader and wait for an event. The other
+ * follower threads will queue up waiting for their turn to become
+ * the leader. When an event occurs, the leader will pick a
+ * follower to become the leader and go on to handle the event.
+ * The consequence of using <ACE_TP_Reactor> is the amortization of
+ * the costs used to creating threads. The context switching cost
+ * will also reduce. More over, the total resources used by
+ * threads are bounded because there are a fixed number of threads.
+ *
+ *
+ * @author Irfan Pyarali <irfan@cs.wustl.edu>
+ * @author Nanbor Wang <nanbor@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_TP_REACTOR_H
+#define ACE_TP_REACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor.h"
+#include "ace/Log_Msg.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_EH_Dispatch_Info
+ *
+ * @brief This structure contains information of the activated event
+ * handler.
+ */
+class ACE_Export ACE_EH_Dispatch_Info
+{
+public:
+
+ ACE_EH_Dispatch_Info (void);
+
+ void set (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ ACE_EH_PTMF callback);
+
+ void reset (void);
+
+ int dispatch (void) const;
+
+ ACE_HANDLE handle_;
+ ACE_Event_Handler *event_handler_;
+ ACE_Reactor_Mask mask_;
+ ACE_EH_PTMF callback_;
+
+ int dispatch_;
+
+private:
+ ACE_UNIMPLEMENTED_FUNC (ACE_EH_Dispatch_Info (const ACE_EH_Dispatch_Info &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_EH_Dispatch_Info &operator= (const ACE_EH_Dispatch_Info &))
+};
+
+
+/**
+ * @class ACE_TP_Token_Guard
+ *
+ * @brief A helper class that helps grabbing, releasing and waiting
+ * on tokens for a thread that tries calling handle_events ().
+ *
+ * In short, this class will be owned by one thread by creating on the
+ * stack. This class gives the status of the ownership of the token
+ * and manages the ownership
+ */
+
+class ACE_Export ACE_TP_Token_Guard
+{
+public:
+
+ /// Constructor that will grab the token for us
+ ACE_TP_Token_Guard (ACE_Select_Reactor_Token &token);
+
+ /// Destructor. This will release the token if it hasnt been
+ /// released till this point
+ ~ACE_TP_Token_Guard (void);
+
+ /// Release the token ..
+ void release_token (void);
+
+ /// Returns whether the thread that created this object ownes the
+ /// token or not.
+ int is_owner (void);
+
+ /// A helper method that grabs the token for us, after which the
+ /// thread that owns that can do some actual work.
+ /// @@todo: Should probably be called acquire_read_token ()
+ int grab_token (ACE_Time_Value *max_wait_time = 0);
+
+ /* A helper method that grabs the token for us, after which the
+ * thread that owns that can do some actual work. This differs from
+ * grab_token () as it uses acquire () to get the token instead of
+ * acquire_read ()
+ */
+ int acquire_token (ACE_Time_Value *max_wait_time = 0);
+
+private:
+
+ /// The Select Reactor token.
+ ACE_Select_Reactor_Token &token_;
+
+ /// Flag that indicate whether the thread that created this object
+ /// owns the token or not. A value of 0 indicates that this class
+ /// hasnt got the token (and hence the thread) and a value of 1
+ /// vice-versa.
+ int owner_;
+
+private:
+
+ ACE_UNIMPLEMENTED_FUNC (ACE_TP_Token_Guard (void))
+};
+
+/**
+ * @class ACE_TP_Reactor
+ *
+ * @brief Specialization of Select Reactor to support thread-pool based
+ * event dispatching.
+ *
+ * One of the short comings of the Select_Reactor in ACE is that
+ * it did not support a thread pool based event dispatching
+ * model, similar to the one in WFMO_Reactor. In
+ * Select_Reactor, only thread can be blocked in <handle_events>
+ * at any given time.
+ * A new Reactor has been added to ACE that removes this
+ * short-coming. TP_Reactor is a specialization of Select
+ * Reactor to support thread-pool based event dispatching. This
+ * Reactor takes advantage of the fact that events reported by
+ * <select> are persistent if not acted upon immediately. It
+ * works by remembering the event handler that just got
+ * activated, releasing the internal lock (so that some other
+ * thread can start waiting in the event loop) and then
+ * dispatching the event handler outside the context of the
+ * Reactor lock.
+ * This Reactor is best suited for situations when the callbacks
+ * to event handlers can take arbitrarily long and/or a number
+ * of threads are available to run the event loops.
+ * Note that callback code in Event Handlers
+ * (e.g. Event_Handler::handle_input) does not have to be
+ * modified or made thread-safe for this Reactor. This is
+ * because an activated Event Handler is suspended in the
+ * Reactor before the upcall is made and resumed after the
+ * upcall completes. Therefore, one Event Handler cannot be
+ * called by multiple threads simultaneously.
+ */
+class ACE_Export ACE_TP_Reactor : public ACE_Select_Reactor
+{
+public:
+
+ // = Initialization and termination methods.
+
+ /// Initialize <ACE_TP_Reactor> with the default size.
+ ACE_TP_Reactor (ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int mask_signals = 1);
+
+ /**
+ * Initialize the <ACE_TP_Reactor> to manage
+ * <max_number_of_handles>. If <restart> is non-0 then the
+ * <ACE_Reactor>'s <handle_events> method will be restarted
+ * automatically when <EINTR> occurs. If <signal_handler> or
+ * <timer_queue> are non-0 they are used as the signal handler and
+ * timer queue, respectively.
+ */
+ ACE_TP_Reactor (size_t max_number_of_handles,
+ int restart = 0,
+ ACE_Sig_Handler * = 0,
+ ACE_Timer_Queue * = 0,
+ int mask_signals = 1);
+
+ // = Event loop drivers.
+
+ /**
+ * This event loop driver that blocks for <max_wait_time> before
+ * returning. It will return earlier if timer events, I/O events,
+ * or signal events occur. Note that <max_wait_time> can be 0, in
+ * which case this method blocks indefinitely until events occur.
+ *
+ * <max_wait_time> is decremented to reflect how much time this call
+ * took. For instance, if a time value of 3 seconds is passed to
+ * handle_events and an event occurs after 2 seconds,
+ * <max_wait_time> will equal 1 second. This can be used if an
+ * application wishes to handle events for some fixed amount of
+ * time.
+ *
+ * Returns the total number of <ACE_Event_Handler>s that were
+ * dispatched, 0 if the <max_wait_time> elapsed without dispatching
+ * any handlers, or -1 if something goes wrong.
+ */
+ virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
+
+ virtual int handle_events (ACE_Time_Value &max_wait_time);
+
+
+ /// The following two overloaded methods are necessary as we dont
+ /// want the TP_Reactor to call handle_close () with the token
+ /// held.
+ /**
+ * Removes the <mask> binding of <eh> from the Select_Reactor. If
+ * there are no more bindings for this <eh> then it is removed from
+ * the Select_Reactor. Note that the Select_Reactor will call
+ * <ACE_Event_Handler::get_handle> to extract the underlying I/O
+ * handle.
+ */
+ virtual int remove_handler (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask);
+
+ /**
+ * Removes the <mask> bind of <Event_Handler> whose handle is
+ * <handle> from the Select_Reactor. If there are no more bindings
+ * for this <eh> then it is removed from the Select_Reactor.
+ */
+ virtual int remove_handler (ACE_HANDLE handle,
+ ACE_Reactor_Mask);
+
+ /**
+ * Removes all the <mask> bindings for handles in the <handle_set>
+ * bind of <Event_Handler>. If there are no more bindings for any
+ * of these handlers then they are removed from the Select_Reactor.
+ */
+ virtual int remove_handler (const ACE_Handle_Set &handle_set,
+ ACE_Reactor_Mask);
+
+ /* @todo: The following methods are not supported. Support for
+ * signals is not available in the TP_Reactor. These methods will be
+ * supported once signal handling is supported. We have to include
+ * these two methods in the TP_Reactor to keep some compilers
+ * silent.
+ */
+ /**
+ * Remove the ACE_Event_Handler currently associated with <signum>.
+ * <sigkey> is ignored in this implementation since there is only
+ * one instance of a signal handler. Install the new disposition
+ * (if given) and return the previous disposition (if desired by the
+ * caller). Returns 0 on success and -1 if <signum> is invalid.
+ */
+ virtual int remove_handler (int signum,
+ ACE_Sig_Action *new_disp,
+ ACE_Sig_Action *old_disp = 0,
+ int sigkey = -1);
+
+ /// Calls <remove_handler> for every signal in <sigset>.
+ virtual int remove_handler (const ACE_Sig_Set &sigset);
+
+ /// Does the reactor allow the application to resume the handle on
+ /// its own ie. can it pass on the control of handle resumption to
+ /// the application. The TP reactor has can allow applications to
+ /// resume handles. So return a +ve value.
+ virtual int resumable_handler (void);
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the <eh> and
+ /// <mask>.
+ virtual int mask_ops (ACE_Event_Handler *eh,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the <handle>
+ /// and <mask>.
+ virtual int mask_ops (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ int ops);
+
+ /// Called from handle events
+ static void no_op_sleep_hook (void *);
+
+ // = Any thread can perform a <handle_events>, override the owner()
+ // methods to avoid the overhead of setting the owner thread.
+
+ /// Set the new owner of the thread and return the old owner.
+ virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0);
+
+ /// Return the current owner of the thread.
+ virtual int owner (ACE_thread_t *);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Internal methods that do the actual work.
+
+
+ /// Dispatch just 1 signal, timer, notification handlers
+ int dispatch_i (ACE_Time_Value *max_wait_time,
+ ACE_TP_Token_Guard &guard);
+
+ /// Get the event that needs dispatching.It could be either a
+ /// signal, timer, notification handlers or return possibly 1 I/O
+ /// handler for dispatching. In the most common use case, this would
+ /// return 1 I/O handler for dispatching
+ int get_event_for_dispatching (ACE_Time_Value *max_wait_time);
+
+ /// Method to handle signals
+ /// NOTE: It is just busted at this point in time.
+ int handle_signals (int &event_count,
+ ACE_TP_Token_Guard &g);
+
+ /// Handle timer events
+ int handle_timer_events (int &event_count,
+ ACE_TP_Token_Guard &g);
+
+ /// Handle notify events
+ int handle_notify_events (int &event_count,
+ ACE_TP_Token_Guard &g);
+
+ /// handle socket events
+ int handle_socket_events (int &event_count,
+ ACE_TP_Token_Guard &g);
+
+ /// This method shouldn't get called.
+ virtual void notify_handle (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask,
+ ACE_Handle_Set &,
+ ACE_Event_Handler *eh,
+ ACE_EH_PTMF callback);
+private:
+
+ /// Get the handle of the notify pipe from the ready set if there is
+ /// an event in the notify pipe.
+ ACE_HANDLE get_notify_handle (void);
+
+ /// Get socket event dispatch information.
+ int get_socket_event_info (ACE_EH_Dispatch_Info &info);
+
+ /// Notify the appropriate <callback> in the context of the <eh>
+ /// associated with <handle> that a particular event has occurred.
+ int dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info);
+
+private:
+ /// Deny access since member-wise won't work...
+ ACE_TP_Reactor (const ACE_TP_Reactor &);
+ ACE_TP_Reactor &operator = (const ACE_TP_Reactor &);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/TP_Reactor.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+#endif /* ACE_TP_REACTOR_H */
diff --git a/ace/Other/TP_Reactor.i b/ace/Other/TP_Reactor.i
new file mode 100644
index 00000000000..9cbec199f80
--- /dev/null
+++ b/ace/Other/TP_Reactor.i
@@ -0,0 +1,93 @@
+/* -*- C++ -*- */
+// $Id$
+
+/************************************************************************/
+// Methods for ACE_EH_Dispatch_Info
+/************************************************************************/
+
+ACE_INLINE void
+ACE_EH_Dispatch_Info::reset (void)
+{
+ this->dispatch_ = 0;
+
+ this->handle_ = ACE_INVALID_HANDLE;
+ this->event_handler_ = 0;
+ this->mask_ = ACE_Event_Handler::NULL_MASK;
+ this->callback_ = 0;
+}
+
+
+ACE_INLINE
+ACE_EH_Dispatch_Info::ACE_EH_Dispatch_Info (void)
+{
+ this->reset ();
+}
+
+ACE_INLINE void
+ACE_EH_Dispatch_Info::set (ACE_HANDLE handle,
+ ACE_Event_Handler *event_handler,
+ ACE_Reactor_Mask mask,
+ ACE_EH_PTMF callback)
+{
+ this->dispatch_ = 1;
+
+ this->handle_ = handle;
+ this->event_handler_ = event_handler;
+ this->mask_ = mask;
+ this->callback_ = callback;
+}
+
+ACE_INLINE int
+ACE_EH_Dispatch_Info::dispatch (void) const
+{
+ return this->dispatch_;
+}
+
+/************************************************************************/
+// Methods for ACE_TP_Token_Guard
+/************************************************************************/
+
+ACE_INLINE
+ACE_TP_Token_Guard::ACE_TP_Token_Guard (ACE_Select_Reactor_Token &token)
+
+ :token_ (token),
+ owner_ (0)
+{
+}
+
+ACE_INLINE
+ACE_TP_Token_Guard::~ACE_TP_Token_Guard (void)
+{
+ if (this->owner_ == 1)
+ {
+ ACE_MT (this->token_.release ());
+ this->owner_ = 0;
+ }
+}
+
+ACE_INLINE void
+ACE_TP_Token_Guard::release_token (void)
+{
+ if (this->owner_)
+ {
+ ACE_MT (this->token_.release ());
+
+ // We are not the owner anymore..
+ this->owner_ = 0;
+ }
+}
+
+ACE_INLINE int
+ACE_TP_Token_Guard::is_owner (void)
+{
+ return this->owner_;
+}
+
+
+/************************************************************************/
+// Methods for ACE_TP_Reactor
+/************************************************************************/
+ACE_INLINE void
+ACE_TP_Reactor::no_op_sleep_hook (void *)
+{
+}
diff --git a/ace/Other/XtReactor.cpp b/ace/Other/XtReactor.cpp
new file mode 100644
index 00000000000..9b86329eb0e
--- /dev/null
+++ b/ace/Other/XtReactor.cpp
@@ -0,0 +1,450 @@
+// $Id$
+
+#include "ace/Synch_T.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/XtReactor.h"
+
+ACE_RCSID(ace, XtReactor, "$Id$")
+
+#if defined (ACE_HAS_XT)
+
+ACE_ALLOC_HOOK_DEFINE (ACE_XtReactor)
+
+// Must be called with lock held
+ACE_XtReactor::ACE_XtReactor (XtAppContext context,
+ size_t size,
+ int restart,
+ ACE_Sig_Handler *h)
+ : ACE_Select_Reactor (size, restart, h),
+ context_ (context),
+ ids_ (0),
+ timeout_ (0)
+{
+ // When the ACE_Select_Reactor is constructed it creates the notify
+ // pipe and registers it with the register_handler_i() method. The
+ // XtReactor overloads this method BUT because the
+ // register_handler_i occurs when constructing the base class
+ // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
+ // is called not the XtReactor register_handler_i(). This means
+ // that the notify pipe is registered with the ACE_Select_Reactor
+ // event handling code not the XtReactor and so notfications don't
+ // work. To get around this we simply close and re-opened the
+ // notification handler in the constructor of the XtReactor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ this->notify_handler_->close ();
+ this->notify_handler_->open (this, 0);
+#endif /* ACE_MT_SAFE */
+}
+
+ACE_XtReactor::~ACE_XtReactor (void)
+{
+ // Delete the remaining items in the linked list.
+
+ while (this->ids_)
+ {
+ ACE_XtReactorID *XtID = this->ids_->next_;
+ delete this->ids_;
+ this->ids_ = XtID;
+ }
+}
+
+// This is just the <wait_for_multiple_events> from ace/Reactor.cpp
+// but we use the Xt functions to wait for an event, not <select>
+
+int
+ACE_XtReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_XtReactor::wait_for_multiple_events");
+ int nfound;
+
+ do
+ {
+ max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
+
+ size_t width = this->handler_rep_.max_handlep1 ();
+ handle_set.rd_mask_ = this->wait_set_.rd_mask_;
+ handle_set.wr_mask_ = this->wait_set_.wr_mask_;
+ handle_set.ex_mask_ = this->wait_set_.ex_mask_;
+ nfound = XtWaitForMultipleEvents (width,
+ handle_set,
+ max_wait_time);
+
+ } while (nfound == -1 && this->handle_error () > 0);
+
+ if (nfound > 0)
+ {
+#if !defined (ACE_WIN32)
+ handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
+ handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_WIN32 */
+ }
+ return nfound; // Timed out or input available
+}
+
+void
+ACE_XtReactor::TimerCallbackProc (XtPointer closure, XtIntervalId * /* id */)
+{
+ ACE_XtReactor *self = (ACE_XtReactor *) closure;
+ self->timeout_ = 0;
+
+ // Deal with any timer events
+ ACE_Select_Reactor_Handle_Set handle_set;
+ self->dispatch (0, handle_set);
+ self->reset_timeout ();
+}
+
+// This could be made shorter if we know which *kind* of event we were
+// about to get. Here we use <select> to find out which one might be
+// available.
+
+void
+ACE_XtReactor::InputCallbackProc (XtPointer closure,
+ int *source,
+ XtInputId *)
+{
+ ACE_XtReactor *self = (ACE_XtReactor *) closure;
+ ACE_HANDLE handle = (ACE_HANDLE) *source;
+
+ // my copy isn't const.
+ ACE_Time_Value zero = ACE_Time_Value::zero;
+
+ ACE_Select_Reactor_Handle_Set wait_set;
+
+ // Deal with one file event.
+
+ // - read which kind of event
+ if (self->wait_set_.rd_mask_.is_set (handle))
+ wait_set.rd_mask_.set_bit (handle);
+ if (self->wait_set_.wr_mask_.is_set (handle))
+ wait_set.wr_mask_.set_bit (handle);
+ if (self->wait_set_.ex_mask_.is_set (handle))
+ wait_set.ex_mask_.set_bit (handle);
+
+ int result = ACE_OS::select (*source + 1,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_, &zero);
+
+ ACE_Select_Reactor_Handle_Set dispatch_set;
+
+ // - Use only that one file event (removes events for other files).
+ if (result > 0)
+ {
+ if (wait_set.rd_mask_.is_set (handle))
+ dispatch_set.rd_mask_.set_bit (handle);
+ if (wait_set.wr_mask_.is_set (handle))
+ dispatch_set.wr_mask_.set_bit (handle);
+ if (wait_set.ex_mask_.is_set (handle))
+ dispatch_set.ex_mask_.set_bit (handle);
+
+ self->dispatch (1, dispatch_set);
+ }
+}
+
+int
+ACE_XtReactor::XtWaitForMultipleEvents (int width,
+ ACE_Select_Reactor_Handle_Set &wait_set,
+ ACE_Time_Value *)
+{
+ // Make sure we have a valid context
+ ACE_ASSERT (this->context_ != 0);
+
+ // Check to make sure our handle's are all usable.
+ ACE_Select_Reactor_Handle_Set temp_set = wait_set;
+
+ if (ACE_OS::select (width,
+ temp_set.rd_mask_,
+ temp_set.wr_mask_,
+ temp_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
+ return -1; // Bad file arguments...
+
+ // Instead of waiting using <select>, just use the Xt mechanism to
+ // wait for a single event.
+
+ // Wait for something to happen.
+ ::XtAppProcessEvent (this->context_, XtIMAll);
+
+ // Reset the width, in case it changed during the upcalls.
+ width = this->handler_rep_.max_handlep1 ();
+
+ // Now actually read the result needed by the <Select_Reactor> using
+ // <select>.
+ return ACE_OS::select (width,
+ wait_set.rd_mask_,
+ wait_set.wr_mask_,
+ wait_set.ex_mask_,
+ (ACE_Time_Value *) &ACE_Time_Value::zero);
+}
+
+XtAppContext
+ACE_XtReactor::context (void) const
+{
+ return this->context_;
+}
+
+void
+ACE_XtReactor::context (XtAppContext context)
+{
+ this->context_ = context;
+}
+
+int
+ACE_XtReactor::register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_XtReactor::register_handler_i");
+
+ // Make sure we have a valid context
+ ACE_ASSERT (this->context_ != 0);
+
+ int result = ACE_Select_Reactor::register_handler_i (handle,
+ handler, mask);
+ if (result == -1)
+ return -1;
+
+ int condition = 0;
+
+#if !defined ACE_WIN32
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, XtInputReadMask);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, XtInputWriteMask);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_SET_BITS (condition, XtInputExceptMask);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, XtInputReadMask);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
+ ACE_SET_BITS (condition, XtInputWriteMask); // connected, you may write
+ ACE_SET_BITS (condition, XtInputReadMask); // connected, you have data/err
+ }
+#else
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
+ ACE_SET_BITS (condition, XtInputReadWinsock);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
+ ACE_SET_BITS (condition, XtInputWriteWinsock);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
+ ACE_NOTSUP_RETURN(-1);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
+ ACE_SET_BITS (condition, XtInputReadWinsock);
+ if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
+ ACE_SET_BITS (condition, XtInputWriteWinsock); // connected, you may write
+ ACE_SET_BITS (condition, XtInputReadWinsock); // connected, you have data/err
+ }
+#endif /* !ACE_WIN32 */
+
+ if (condition != 0)
+ {
+ ACE_XtReactorID *XtID = this->ids_;
+
+ while(XtID)
+ {
+ if (XtID->handle_ == handle)
+ {
+ ::XtRemoveInput (XtID->id_);
+
+ XtID->id_ = ::XtAppAddInput (this->context_,
+ (int) handle,
+ (XtPointer) condition,
+ InputCallbackProc,
+ (XtPointer) this);
+ return 0;
+ }
+ else
+ XtID = XtID->next_;
+ }
+
+ ACE_NEW_RETURN (XtID,
+ ACE_XtReactorID,
+ -1);
+ XtID->next_ = this->ids_;
+ XtID->handle_ = handle;
+ XtID->id_ = ::XtAppAddInput (this->context_,
+ (int) handle,
+ (XtPointer) condition,
+ InputCallbackProc,
+ (XtPointer) this);
+ this->ids_ = XtID;
+ }
+ return 0;
+}
+
+int
+ACE_XtReactor::register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::register_handler_i (handles,
+ handler,
+ mask);
+}
+
+int
+ACE_XtReactor::remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_XtReactor::remove_handler_i");
+
+ // In the registration phase we registered first with
+ // ACE_Select_Reactor and then with X. Now we are now doing things
+ // in reverse order.
+
+ // First clean up the corresponding X11Input.
+ this->remove_XtInput (handle);
+
+ // Now let the reactor do its work.
+ return ACE_Select_Reactor::remove_handler_i (handle,
+ mask);
+}
+
+void
+ACE_XtReactor::remove_XtInput (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_XtReactor::remove_XtInput");
+
+ ACE_XtReactorID *XtID = this->ids_;
+
+ if (XtID)
+ {
+ if (XtID->handle_ == handle)
+ {
+ ::XtRemoveInput (XtID->id_);
+ this->ids_ = XtID->next_;
+ delete XtID;
+ return;
+ }
+
+ ACE_XtReactorID *NextID = XtID->next_;
+
+ while (NextID)
+ {
+ if (NextID->handle_ == handle)
+ {
+ ::XtRemoveInput(NextID->id_);
+ XtID->next_ = NextID->next_;
+ delete NextID;
+ return;
+ }
+ else
+ {
+ XtID = NextID;
+ NextID = NextID->next_;
+ }
+ }
+ }
+}
+
+int
+ACE_XtReactor::remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask mask)
+{
+ return ACE_Select_Reactor::remove_handler_i (handles,
+ mask);
+}
+
+// The following functions ensure that there is an Xt timeout for the
+// first timeout in the Reactor's Timer_Queue.
+
+void
+ACE_XtReactor::reset_timeout (void)
+{
+ // Make sure we have a valid context
+ ACE_ASSERT (this->context_ != 0);
+
+ if (timeout_)
+ ::XtRemoveTimeOut (timeout_);
+ timeout_ = 0;
+
+ ACE_Time_Value *max_wait_time =
+ this->timer_queue_->calculate_timeout (0);
+
+ if (max_wait_time)
+ timeout_ = ::XtAppAddTimeOut (this->context_,
+ max_wait_time->msec (),
+ TimerCallbackProc,
+ (XtPointer) this);
+}
+
+int
+ACE_XtReactor::reset_timer_interval
+ (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_XtReactor::reset_timer_interval");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ int result = ACE_Select_Reactor::timer_queue_->reset_interval
+ (timer_id,
+ interval);
+
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+long
+ACE_XtReactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_XtReactor::schedule_timer");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
+
+ long result = ACE_Select_Reactor::schedule_timer (handler,
+ arg,
+ delay_time,
+ interval);
+ if (result == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return result;
+ }
+}
+
+int
+ACE_XtReactor::cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_XtReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (handler,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+int
+ACE_XtReactor::cancel_timer (long timer_id,
+ const void **arg,
+ int dont_call_handle_close)
+{
+ ACE_TRACE ("ACE_XtReactor::cancel_timer");
+
+ if (ACE_Select_Reactor::cancel_timer (timer_id,
+ arg,
+ dont_call_handle_close) == -1)
+ return -1;
+ else
+ {
+ this->reset_timeout ();
+ return 0;
+ }
+}
+
+#endif /* ACE_HAS_XT */
diff --git a/ace/Other/XtReactor.h b/ace/Other/XtReactor.h
new file mode 100644
index 00000000000..0104e946952
--- /dev/null
+++ b/ace/Other/XtReactor.h
@@ -0,0 +1,136 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file XtReactor.h
+ *
+ * $Id$
+ *
+ * @author Eric C. Newton's <ecn@clark.net>
+ * @author Kirill Rybaltchenko <Kirill.Rybaltchenko@cern.ch>
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_XTREACTOR_H
+#define ACE_XTREACTOR_H
+#include "ace/pre.h"
+
+#include "ace/Select_Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_XT)
+
+//#define String XtString
+#include /**/ <X11/Intrinsic.h>
+//#undef String
+
+/**
+ * @class ACE_XtReactorID
+ *
+ * @brief This little class is necessary due to the way that Microsoft
+ * implements sockets to be pointers rather than indices.
+ */
+class ACE_Export ACE_XtReactorID
+{
+public:
+ /// Magic cookie.
+ XtInputId id_;
+
+ /// Underlying handle.
+ ACE_HANDLE handle_;
+
+ /// Pointer to next node in the linked list.
+ ACE_XtReactorID *next_;
+};
+
+/**
+ * @class ACE_XtReactor
+ *
+ * @brief An object-oriented event demultiplexor and event handler
+ * dispatcher that uses the X Toolkit functions.
+ */
+class ACE_Export ACE_XtReactor : public ACE_Select_Reactor
+{
+public:
+ // = Initialization and termination methods.
+ ACE_XtReactor (XtAppContext context = 0,
+ size_t size = DEFAULT_SIZE,
+ int restart = 0,
+ ACE_Sig_Handler * = 0);
+ virtual ~ACE_XtReactor (void);
+
+ XtAppContext context (void) const;
+ void context (XtAppContext);
+
+ // = Timer operations.
+ virtual long schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delay_time,
+ const ACE_Time_Value &interval);
+ virtual int reset_timer_interval (long timer_id,
+ const ACE_Time_Value &interval);
+ virtual int cancel_timer (ACE_Event_Handler *handler,
+ int dont_call_handle_close = 1);
+
+ virtual int cancel_timer (long timer_id,
+ const void **arg = 0,
+ int dont_call_handle_close = 1);
+
+protected:
+ // = Register timers/handles with Xt.
+ /// Register a single <handler>.
+ virtual int register_handler_i (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Register a set of <handlers>.
+ virtual int register_handler_i (const ACE_Handle_Set &handles,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask);
+
+ /// Remove the <handler> associated with this <handle>.
+ virtual int remove_handler_i (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+
+ /// Remove a set of <handles>.
+ virtual int remove_handler_i (const ACE_Handle_Set &handles,
+ ACE_Reactor_Mask);
+
+ /// Removes an Xt handle.
+ virtual void remove_XtInput (ACE_HANDLE handle);
+
+ /// Wait for events to occur.
+ virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+ ///Wait for Xt events to occur.
+ virtual int XtWaitForMultipleEvents (int,
+ ACE_Select_Reactor_Handle_Set &,
+ ACE_Time_Value *);
+
+ XtAppContext context_;
+ ACE_XtReactorID *ids_;
+ XtIntervalId timeout_;
+
+private:
+ /// This method ensures there's an Xt timeout for the first timeout
+ /// in the Reactor's Timer_Queue.
+ void reset_timeout (void);
+
+ // = Integrate with the X callback function mechanism.
+ static void TimerCallbackProc (XtPointer closure, XtIntervalId *id);
+ static void InputCallbackProc (XtPointer closure, int* source, XtInputId *id);
+
+ /// Deny access since member-wise won't work...
+ ACE_XtReactor (const ACE_XtReactor &);
+ ACE_XtReactor &operator = (const ACE_XtReactor &);
+};
+#endif /* ACE_HAS_XT */
+
+#include "ace/post.h"
+#endif /* ACE_XTREACTOR_H */
diff --git a/ace/Sockets/IPC_SAP.cpp b/ace/Sockets/IPC_SAP.cpp
new file mode 100644
index 00000000000..39b73436c96
--- /dev/null
+++ b/ace/Sockets/IPC_SAP.cpp
@@ -0,0 +1,182 @@
+// $Id$
+
+#include "ace/IPC_SAP.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/IPC_SAP.i"
+#endif
+
+ACE_RCSID(ace, IPC_SAP, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_IPC_SAP)
+
+void
+ACE_IPC_SAP::dump (void) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("handle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npid_ = %d"), this->pid_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Cache for the process ID.
+pid_t ACE_IPC_SAP::pid_ = 0;
+
+// This is the do-nothing constructor. It does not perform a
+// ACE_OS::socket system call.
+
+ACE_IPC_SAP::ACE_IPC_SAP (void)
+ : handle_ (ACE_INVALID_HANDLE)
+{
+ // ACE_TRACE ("ACE_IPC_SAP::ACE_IPC_SAP");
+}
+
+int
+ACE_IPC_SAP::enable (int value) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::enable");
+
+ // First-time in initialization.
+ if (ACE_IPC_SAP::pid_ == 0)
+ ACE_IPC_SAP::pid_ = ACE_OS::getpid ();
+
+#if defined (ACE_WIN32) || defined (VXWORKS)
+ switch (value)
+ {
+ case ACE_NONBLOCK:
+ {
+ // nonblocking argument (1)
+ // blocking: (0)
+ u_long nonblock = 1;
+ return ACE_OS::ioctl (this->handle_,
+ FIONBIO,
+ &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else /* ! ACE_WIN32 && ! VXWORKS */
+ switch (value)
+ {
+#if defined (SIGURG)
+ case SIGURG:
+ case ACE_SIGURG:
+#if defined (F_SETOWN)
+ return ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ ACE_IPC_SAP::pid_);
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN */
+#endif /* SIGURG */
+#if defined (SIGIO)
+ case SIGIO:
+ case ACE_SIGIO:
+#if defined (F_SETOWN) && defined (FASYNC)
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ ACE_IPC_SAP::pid_) == -1
+ || ACE_Flag_Manip::set_flags (this->handle_,
+ FASYNC) == -1)
+ return -1;
+ break;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN && FASYNC */
+#endif /* SIGIO <== */
+#if defined (F_SETFD)
+ case ACE_CLOEXEC:
+ // Enables the close-on-exec flag.
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETFD,
+ 1) == -1)
+ return -1;
+ break;
+#endif /* F_SETFD */
+ case ACE_NONBLOCK:
+ if (ACE_Flag_Manip::set_flags (this->handle_,
+ ACE_NONBLOCK) == ACE_INVALID_HANDLE)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#endif /* ! ACE_WIN32 && ! VXWORKS */
+
+ /* NOTREACHED */
+}
+
+int
+ACE_IPC_SAP::disable (int value) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::disable");
+
+#if defined (ACE_WIN32) || defined (VXWORKS)
+ switch (value)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ u_long nonblock = 0;
+ return ACE_OS::ioctl (this->handle_,
+ FIONBIO,
+ &nonblock);
+ }
+ default:
+ ACE_NOTSUP_RETURN (-1);
+ }
+#else /* ! ACE_WIN32 && ! VXWORKS */
+ switch (value)
+ {
+#if defined (SIGURG)
+ case SIGURG:
+ case ACE_SIGURG:
+#if defined (F_SETOWN)
+ return ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ 0);
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN */
+#endif /* SIGURG */
+#if defined (SIGIO)
+ case SIGIO:
+ case ACE_SIGIO:
+#if defined (F_SETOWN) && defined (FASYNC)
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETOWN,
+ 0) == -1
+ || ACE_Flag_Manip::clr_flags (this->handle_,
+ FASYNC) == -1)
+ return -1;
+ break;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* F_SETOWN && FASYNC */
+#endif /* SIGIO <== */
+#if defined (F_SETFD)
+ case ACE_CLOEXEC:
+ // Disables the close-on-exec flag.
+ if (ACE_OS::fcntl (this->handle_,
+ F_SETFD,
+ 0) == -1)
+ return -1;
+ break;
+#endif /* F_SETFD */
+ case ACE_NONBLOCK:
+ if (ACE_Flag_Manip::clr_flags (this->handle_,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#endif /* ! ACE_WIN32 && ! VXWORKS */
+ /* NOTREACHED */
+}
diff --git a/ace/Sockets/IPC_SAP.h b/ace/Sockets/IPC_SAP.h
new file mode 100644
index 00000000000..86d9a3e2d5c
--- /dev/null
+++ b/ace/Sockets/IPC_SAP.h
@@ -0,0 +1,84 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file IPC_SAP.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_IPC_SAP_H
+#define ACE_IPC_SAP_H
+#include "ace/pre.h"
+
+#include "ace/Flag_Manip.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_IPC_SAP
+ *
+ * @brief Defines the member functions for the base class of the
+ * ACE_IPC_SAP abstraction.
+ */
+class ACE_Export ACE_IPC_SAP
+{
+public:
+ /// Default dtor.
+ ~ACE_IPC_SAP (void);
+
+ /// Interface for <ioctl>.
+ int control (int cmd, void *) const;
+
+ // = Common I/O handle options related to sockets.
+
+ /**
+ * Enable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int enable (int value) const;
+
+ /**
+ * Disable asynchronous I/O (ACE_SIGIO), urgent data (ACE_SIGURG),
+ * non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC),
+ * which is passed as the <value>.
+ */
+ int disable (int value) const;
+
+ /// Get the underlying handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Set the underlying handle.
+ void set_handle (ACE_HANDLE handle);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Ensure that ACE_IPC_SAP is an abstract base class.
+ /// Default constructor.
+ ACE_IPC_SAP (void);
+
+private:
+ /// Underlying I/O handle.
+ ACE_HANDLE handle_;
+
+ /// Cache the process ID.
+ static pid_t pid_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/IPC_SAP.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_IPC_SAP_H */
diff --git a/ace/Sockets/IPC_SAP.i b/ace/Sockets/IPC_SAP.i
new file mode 100644
index 00000000000..63ccc967711
--- /dev/null
+++ b/ace/Sockets/IPC_SAP.i
@@ -0,0 +1,37 @@
+/* -*- C++ -*- */
+// $Id$
+
+// IPC_SAP.i
+
+// Used to return the underlying handle_.
+
+ASYS_INLINE
+ACE_IPC_SAP::~ACE_IPC_SAP (void)
+{
+ // ACE_TRACE ("ACE_IPC_SAP::~ACE_IPC_SAP");
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_IPC_SAP::get_handle (void) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::get_handle");
+ return this->handle_;
+}
+
+// Used to set the underlying handle_.
+
+ASYS_INLINE void
+ACE_IPC_SAP::set_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_IPC_SAP::set_handle");
+ this->handle_ = handle;
+}
+
+// Provides access to the ACE_OS::ioctl system call.
+
+ASYS_INLINE int
+ACE_IPC_SAP::control (int cmd, void *arg) const
+{
+ ACE_TRACE ("ACE_IPC_SAP::control");
+ return ACE_OS::ioctl (this->handle_, cmd, arg);
+}
diff --git a/ace/Sockets/LSOCK.cpp b/ace/Sockets/LSOCK.cpp
new file mode 100644
index 00000000000..427d2117f06
--- /dev/null
+++ b/ace/Sockets/LSOCK.cpp
@@ -0,0 +1,172 @@
+// $Id$
+
+#include "ace/LSOCK.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK)
+
+void
+ACE_LSOCK::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("aux_handle_ = %d"), this->aux_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_MSG)
+// This routine sends an open file descriptor to <this->handle_>.
+
+int
+ACE_LSOCK::send_handle (const ACE_HANDLE handle) const
+{
+ ACE_TRACE ("ACE_LSOCK::send_handle");
+ u_char a[2];
+ iovec iov;
+ msghdr send_msg;
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ char cmsgbuf[ACE_BSD_CONTROL_MSG_LEN];
+ cmsghdr *cmsgptr = (cmsghdr *) cmsgbuf;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ a[0] = 0xab;
+ a[1] = 0xcd;
+ iov.iov_base = (char *) a;
+ iov.iov_len = sizeof a;
+ send_msg.msg_iov = &iov;
+ send_msg.msg_iovlen = 1;
+ send_msg.msg_name = 0;
+ send_msg.msg_namelen = 0;
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ cmsgptr->cmsg_level = SOL_SOCKET;
+ cmsgptr->cmsg_type = SCM_RIGHTS;
+ cmsgptr->cmsg_len = sizeof cmsgbuf;
+ send_msg.msg_control = cmsgbuf;
+ send_msg.msg_controllen = sizeof cmsgbuf;
+ *(ACE_HANDLE *) CMSG_DATA (cmsgptr) = handle;
+ send_msg.msg_flags = 0;
+#else
+ send_msg.msg_accrights = (char *) &handle;
+ send_msg.msg_accrightslen = sizeof handle;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ return ACE_OS::sendmsg (this->get_handle (), &send_msg, 0);
+}
+
+// This file receives an open file descriptor from <this->handle_>.
+// Note, this routine returns -1 if problems occur, 0 if we recv a
+// message that does not have file descriptor in it, and 1 otherwise.
+
+int
+ACE_LSOCK::recv_handle (ACE_HANDLE &handle, char *pbuf, int *len) const
+{
+ ACE_TRACE ("ACE_LSOCK::recv_handle");
+ u_char a[2];
+ iovec iov;
+ msghdr recv_msg;
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ char cmsgbuf[ACE_BSD_CONTROL_MSG_LEN];
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ if (pbuf != 0 && len != 0)
+ {
+ iov.iov_base = pbuf;
+ iov.iov_len = *len;
+ }
+ else
+ {
+ iov.iov_base = (char *) a;
+ iov.iov_len = sizeof a;
+ }
+
+ recv_msg.msg_iov = &iov;
+ recv_msg.msg_iovlen = 1;
+ recv_msg.msg_name = 0;
+ recv_msg.msg_namelen = 0;
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ recv_msg.msg_control = cmsgbuf;
+ recv_msg.msg_controllen = sizeof cmsgbuf;
+#else
+ recv_msg.msg_accrights = (char *) &handle;
+ recv_msg.msg_accrightslen = sizeof handle;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+#if defined (ACE_HAS_STREAMS)
+
+ ssize_t nbytes = ACE_OS::recvmsg (this->get_handle (), &recv_msg, 0);
+
+ if (nbytes != ACE_INVALID_HANDLE)
+ {
+ if (len != 0)
+ *len = nbytes;
+
+ if (nbytes == sizeof a
+ && ((u_char *) iov.iov_base)[0] == 0xab
+ && ((u_char *) iov.iov_base)[1] == 0xcd)
+ {
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ cmsghdr *cmsgptr = (cmsghdr *) cmsgbuf;
+ handle = *(ACE_HANDLE *) CMSG_DATA (cmsgptr);
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+ return 1;
+ }
+ else
+ return 0;
+ }
+#else
+ ssize_t nbytes = ACE_OS::recvmsg (this->get_handle (),
+ &recv_msg,
+ MSG_PEEK);
+
+ if (nbytes != ACE_INVALID_HANDLE)
+ {
+ if (nbytes == sizeof a
+ && ((u_char *) iov.iov_base)[0] == 0xab
+ && ((u_char *) iov.iov_base)[1] == 0xcd)
+ {
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ // Close down the socket that was returned by the MSG_PEEK.
+ ACE_OS::closesocket (*(ACE_HANDLE *) CMSG_DATA ((cmsghdr *) cmsgbuf));
+ recv_msg.msg_control = cmsgbuf;
+ recv_msg.msg_controllen = sizeof cmsgbuf;
+#else
+ recv_msg.msg_accrights = (char *) &handle;
+ recv_msg.msg_accrightslen = sizeof handle;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ if (ACE_OS::recvmsg (this->get_handle (),
+ &recv_msg, 0) == ACE_INVALID_HANDLE)
+ return ACE_INVALID_HANDLE;
+ else
+ {
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ cmsghdr *cmsgptr = (cmsghdr *) cmsgbuf;
+ handle = *(ACE_HANDLE *) CMSG_DATA (cmsgptr);
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+ return 1;
+ }
+ }
+ else
+ {
+ if (len != 0)
+ *len = nbytes;
+ return 0;
+ }
+ }
+#endif /* ACE_HAS_STREAMS */
+ else
+ return ACE_INVALID_HANDLE;
+}
+#endif /* ACE_HAS_MSG */
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK.h b/ace/Sockets/LSOCK.h
new file mode 100644
index 00000000000..b307e99e2e0
--- /dev/null
+++ b/ace/Sockets/LSOCK.h
@@ -0,0 +1,77 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file LSOCK.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_H
+#define ACE_LOCAL_SOCK_H
+#include "ace/pre.h"
+
+#include "ace/SOCK.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_LSOCK
+ *
+ * @brief Create a Local ACE_SOCK, which is used for passing file
+ * descriptors.
+ */
+class ACE_Export ACE_LSOCK
+{
+public:
+#if defined (ACE_HAS_MSG)
+ /// Send an open FD to another process.
+ int send_handle (const ACE_HANDLE handle) const;
+
+ /// Recv an open FD from another process.
+ int recv_handle (ACE_HANDLE &handles,
+ char *pbuf = 0,
+ int *len = 0) const;
+#endif /* ACE_HAS_MSG */
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ // = Ensure that ACE_LSOCK is an abstract base class
+
+ /// Default constructor.
+ ACE_LSOCK (void);
+
+ /// Initialize based on <handle>
+ ACE_LSOCK (ACE_HANDLE handle);
+
+ /// Get handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Set handle.
+ void set_handle (ACE_HANDLE handle);
+
+private:
+ /// An auxiliary handle used to avoid virtual base classes...
+ ACE_HANDLE aux_handle_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK.i"
+#endif
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_H */
diff --git a/ace/Sockets/LSOCK.i b/ace/Sockets/LSOCK.i
new file mode 100644
index 00000000000..c5b0057fa0e
--- /dev/null
+++ b/ace/Sockets/LSOCK.i
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+// $Id$
+
+// LSOCK.i
+
+// Simple-minded constructor.
+
+ASYS_INLINE
+ACE_LSOCK::ACE_LSOCK (void)
+ : aux_handle_ (ACE_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_LSOCK::ACE_LSOCK");
+}
+
+// Sets the underlying file descriptor.
+
+ASYS_INLINE void
+ACE_LSOCK::set_handle (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_LSOCK::set_handle");
+ this->aux_handle_ = handle;
+}
+
+// Gets the underlying file descriptor.
+
+ASYS_INLINE ACE_HANDLE
+ACE_LSOCK::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK::get_handle");
+ return this->aux_handle_;
+}
+
+// Sets the underlying file descriptor.
+
+ASYS_INLINE
+ACE_LSOCK::ACE_LSOCK (ACE_HANDLE handle)
+ : aux_handle_ (handle)
+{
+ ACE_TRACE ("ACE_LSOCK::ACE_LSOCK");
+}
diff --git a/ace/Sockets/LSOCK_Acceptor.cpp b/ace/Sockets/LSOCK_Acceptor.cpp
new file mode 100644
index 00000000000..9c4574a50d3
--- /dev/null
+++ b/ace/Sockets/LSOCK_Acceptor.cpp
@@ -0,0 +1,135 @@
+// LSOCK_Acceptor.cpp
+// $Id$
+
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_Acceptor, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Acceptor)
+
+// Return the local endpoint address.
+
+int
+ACE_LSOCK_Acceptor::get_local_addr (ACE_Addr &a) const
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::get_local_addr");
+
+ ACE_UNIX_Addr& target = ACE_dynamic_cast (ACE_UNIX_Addr &, a);
+
+ target = this->local_addr_;
+
+ return 0;
+}
+
+void
+ACE_LSOCK_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->local_addr_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// Do nothing routine for constructor.
+
+ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor");
+}
+
+int
+ACE_LSOCK_Acceptor::open (const ACE_Addr &remote_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::open");
+ this->local_addr_ = *((ACE_UNIX_Addr *) &remote_sap); // This is a gross hack...
+ return ACE_SOCK_Acceptor::open (remote_sap, reuse_addr,
+ protocol_family, backlog, protocol);
+}
+
+// General purpose routine for performing server ACE_SOCK creation.
+
+ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor (const ACE_Addr &remote_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor");
+ if (this->open (remote_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor"));
+}
+
+// General purpose routine for accepting new connections.
+
+int
+ACE_LSOCK_Acceptor::accept (ACE_LSOCK_Stream &new_stream,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::accept");
+
+ int in_blocking_mode = 0;
+ if (this->shared_accept_start (timeout,
+ restart,
+ in_blocking_mode) == -1)
+ return -1;
+ else
+ {
+ sockaddr *addr = 0;
+ int len = 0;
+
+ if (remote_addr != 0)
+ {
+ len = remote_addr->get_size ();
+ addr = (sockaddr *) remote_addr->get_addr ();
+ }
+
+ do
+ new_stream.set_handle (ACE_OS::accept (this->get_handle (),
+ addr,
+ &len));
+ while (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && restart != 0
+ && errno == EINTR
+ && timeout == 0);
+
+ // Reset the size of the addr, which is only necessary for UNIX
+ // domain sockets.
+ if (new_stream.get_handle () != ACE_INVALID_HANDLE
+ && remote_addr != 0)
+ remote_addr->set_size (len);
+ }
+
+ return this->shared_accept_finish (new_stream,
+ in_blocking_mode,
+ reset_new_handle);
+}
+
+// Close down the UNIX domain stream and remove the rendezvous point
+// from the file system.
+
+int
+ACE_LSOCK_Acceptor::remove (void)
+{
+ ACE_TRACE ("ACE_LSOCK_Acceptor::remove");
+ int result = this->close ();
+ return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1
+ || result == -1 ? -1 : 0;
+}
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK_Acceptor.h b/ace/Sockets/LSOCK_Acceptor.h
new file mode 100644
index 00000000000..852dccfbc44
--- /dev/null
+++ b/ace/Sockets/LSOCK_Acceptor.h
@@ -0,0 +1,90 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file LSOCK_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_ACCEPTOR_H
+#define ACE_LOCAL_SOCK_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK_Stream.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// Forward decl.
+class ACE_Reactor;
+
+/**
+ * @class ACE_LSOCK_Acceptor
+ *
+ * @brief Defines the format and interface for the acceptor side of the
+ * local ACE_SOCK ACE_Stream.
+ */
+class ACE_Export ACE_LSOCK_Acceptor : public ACE_SOCK_Acceptor
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_LSOCK_Acceptor (void);
+
+ /// Initiate a passive mode socket.
+ ACE_LSOCK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNIX,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Initiate a passive mode socket.
+ int open (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNIX,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Accept a new data transfer connection.
+ int accept (ACE_LSOCK_Stream &new_ipc_sap,
+ ACE_Addr * = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ /// Close down the ACE_LSOCK and remove the rendezvous point from the
+ /// file system.
+ int remove (void);
+
+ /// Return the local endpoint address.
+ int get_local_addr (ACE_Addr &) const;
+
+ // = Meta-type info
+ typedef ACE_UNIX_Addr PEER_ADDR;
+ typedef ACE_LSOCK_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Address of our rendezvous point.
+ ACE_UNIX_Addr local_addr_;
+};
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_ACCEPTOR_H */
diff --git a/ace/Sockets/LSOCK_CODgram.cpp b/ace/Sockets/LSOCK_CODgram.cpp
new file mode 100644
index 00000000000..5bce9e7887d
--- /dev/null
+++ b/ace/Sockets/LSOCK_CODgram.cpp
@@ -0,0 +1,56 @@
+// LSOCK_CODgram.cpp
+// $Id$
+
+#include "ace/LSOCK_CODgram.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_CODgram, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_CODgram.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_CODgram)
+
+void
+ACE_LSOCK_CODgram::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_SOCK_CODgram::dump ();
+ ACE_LSOCK::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+/* Here's the general-purpose open routine. */
+
+int
+ACE_LSOCK_CODgram::open (const ACE_Addr &remote,
+ const ACE_Addr &local,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::open");
+ if (ACE_SOCK_CODgram::open (remote, local, protocol_family,
+ protocol) == -1)
+ return -1;
+ ACE_LSOCK::set_handle (this->get_handle ());
+ return 0;
+}
+
+/* Create a local ACE_SOCK datagram. */
+
+ACE_LSOCK_CODgram::ACE_LSOCK_CODgram (const ACE_Addr &remote,
+ const ACE_Addr &local,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::ACE_LSOCK_CODgram");
+ if (this->open (remote, local, protocol_family,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_LSOCK_CODgram")));
+}
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK_CODgram.h b/ace/Sockets/LSOCK_CODgram.h
new file mode 100644
index 00000000000..f9bbf138654
--- /dev/null
+++ b/ace/Sockets/LSOCK_CODgram.h
@@ -0,0 +1,73 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file LSOCK_CODgram.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_CODGRAM_H
+#define ACE_LOCAL_SOCK_CODGRAM_H
+#include "ace/pre.h"
+
+#include "ace/LSOCK.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_CODgram.h"
+#include "ace/Addr.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_LSOCK_CODgram
+ *
+ * @brief Defines the member functions for the <ACE_LSOCK> connected
+ * datagram abstraction.
+ */
+class ACE_Export ACE_LSOCK_CODgram : public ACE_SOCK_CODgram, public ACE_LSOCK
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_LSOCK_CODgram (void);
+
+ /// Initiate a connected-datagram.
+ ACE_LSOCK_CODgram (const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int protocol_family = PF_UNIX,
+ int protocol = 0);
+
+ /// Initiate a connected-datagram.
+ int open (const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int protocol_family = PF_UNIX,
+ int protocol = 0);
+
+ /// Get underlying handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Set underlying handle.
+ void set_handle (ACE_HANDLE);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_CODgram.i"
+#endif
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_CODGRAM_H */
diff --git a/ace/Sockets/LSOCK_CODgram.i b/ace/Sockets/LSOCK_CODgram.i
new file mode 100644
index 00000000000..80a6071770c
--- /dev/null
+++ b/ace/Sockets/LSOCK_CODgram.i
@@ -0,0 +1,27 @@
+/* -*- C++ -*- */
+// $Id$
+
+// LSOCK_CODgram.i
+
+// Do nothing constructor.
+
+ASYS_INLINE
+ACE_LSOCK_CODgram::ACE_LSOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::ACE_LSOCK_CODgram");
+}
+
+ASYS_INLINE void
+ACE_LSOCK_CODgram::set_handle (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::set_handle");
+ this->ACE_SOCK_CODgram::set_handle (h);
+ this->ACE_LSOCK::set_handle (h);
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_LSOCK_CODgram::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_CODgram::get_handle");
+ return this->ACE_SOCK_CODgram::get_handle ();
+}
diff --git a/ace/Sockets/LSOCK_Connector.cpp b/ace/Sockets/LSOCK_Connector.cpp
new file mode 100644
index 00000000000..8bd17fd81c1
--- /dev/null
+++ b/ace/Sockets/LSOCK_Connector.cpp
@@ -0,0 +1,58 @@
+// LSOCK_Connector.cpp
+// $Id$
+
+#include "ace/LSOCK_Connector.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_Connector, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Connector.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Connector)
+
+void
+ACE_LSOCK_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Connector::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+ACE_LSOCK_Connector::ACE_LSOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_LSOCK_Connector::ACE_LSOCK_Connector");
+}
+
+// Establish a connection.
+ACE_LSOCK_Connector::ACE_LSOCK_Connector (ACE_LSOCK_Stream &new_stream,
+ const ACE_UNIX_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol_family,
+ int protocol)
+ : ACE_SOCK_Connector (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol_family,
+ protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Connector::ACE_LSOCK_Connector");
+ // This is necessary due to the weird inheritance relationships of
+ // ACE_LSOCK_Stream.
+ new_stream.set_handle (new_stream.get_handle ());
+}
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK_Connector.h b/ace/Sockets/LSOCK_Connector.h
new file mode 100644
index 00000000000..21aa4dd2130
--- /dev/null
+++ b/ace/Sockets/LSOCK_Connector.h
@@ -0,0 +1,108 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file LSOCK_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_LOCAL_SOCK_CONNECTOR_H
+#define ACE_LOCAL_SOCK_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Connector.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/LSOCK_Stream.h"
+#include "ace/UNIX_Addr.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_LSOCK_Connector
+ *
+ * @brief Defines the format and interface for the connector side of
+ * the <ACE_LSOCK_Stream>.
+ */
+class ACE_Export ACE_LSOCK_Connector : public ACE_SOCK_Connector
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_LSOCK_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ ACE_LSOCK_Connector (ACE_LSOCK_Stream &new_stream,
+ const ACE_UNIX_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol_family = PF_UNIX,
+ int protocol = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out. If the
+ * time expires before the connection is made <errno == ETIME>. The
+ * <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_LSOCK_Stream &new_stream,
+ const ACE_UNIX_Addr &remote_sap,
+ ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protcol_family = PF_UNIX,
+ int protocol = 0);
+
+ // = Meta-type info
+ typedef ACE_UNIX_Addr PEER_ADDR;
+ typedef ACE_LSOCK_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Connector.i"
+#endif
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_CONNECTOR_H */
diff --git a/ace/Sockets/LSOCK_Connector.i b/ace/Sockets/LSOCK_Connector.i
new file mode 100644
index 00000000000..4c0a18663f5
--- /dev/null
+++ b/ace/Sockets/LSOCK_Connector.i
@@ -0,0 +1,29 @@
+/* -*- C++ -*- */
+// $Id$
+
+// LSOCK_Connector.i
+
+// Establish a connection.
+
+ASYS_INLINE int
+ACE_LSOCK_Connector::connect (ACE_LSOCK_Stream &new_stream,
+ const ACE_UNIX_Addr &remote_sap,
+ ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Connector::connect");
+ int result = ACE_SOCK_Connector::connect (new_stream, remote_sap,
+ timeout, local_sap,
+ reuse_addr, flags, perms,
+ protocol_family, protocol);
+ if (result != -1)
+ // This is necessary due to the weird inheritance relationships of ACE_LSOCK_Stream.
+ new_stream.set_handle (new_stream.get_handle ());
+ return result;
+}
+
diff --git a/ace/Sockets/LSOCK_Dgram.cpp b/ace/Sockets/LSOCK_Dgram.cpp
new file mode 100644
index 00000000000..fd1a67c1363
--- /dev/null
+++ b/ace/Sockets/LSOCK_Dgram.cpp
@@ -0,0 +1,66 @@
+// $Id$
+
+#include "ace/LSOCK_Dgram.h"
+#include "ace/Log_Msg.h"
+
+
+ACE_RCSID(ace, LSOCK_Dgram, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Dgram.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Dgram)
+
+void
+ACE_LSOCK_Dgram::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_SOCK_Dgram::dump ();
+ ACE_LSOCK::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+// The "do nothing" constructor.
+
+ACE_LSOCK_Dgram::ACE_LSOCK_Dgram (void)
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::ACE_LSOCK_Dgram");
+}
+
+// Here's the general-purpose open routine.
+
+int
+ACE_LSOCK_Dgram::open (const ACE_Addr &local,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::open");
+ if (ACE_SOCK_Dgram::open (local,
+ protocol_family,
+ protocol) == -1)
+ return -1;
+ ACE_LSOCK::set_handle (this->ACE_SOCK_Dgram::get_handle ());
+ return 0;
+}
+
+// Create a local ACE_SOCK datagram.
+
+ACE_LSOCK_Dgram::ACE_LSOCK_Dgram (const ACE_Addr &local,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::ACE_LSOCK_Dgram");
+ if (this->open (local,
+ protocol_family,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_LSOCK_Dgram")));
+}
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK_Dgram.h b/ace/Sockets/LSOCK_Dgram.h
new file mode 100644
index 00000000000..0bc90cf3008
--- /dev/null
+++ b/ace/Sockets/LSOCK_Dgram.h
@@ -0,0 +1,70 @@
+/* -*- C++ -*- */
+
+
+//=============================================================================
+/**
+ * @file LSOCK_Dgram.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_DGRAM_H
+#define ACE_LOCAL_SOCK_DGRAM_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Dgram.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/LSOCK.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_LSOCK_Dgram
+ *
+ * @brief Create a Local ACE_SOCK datagram.
+ */
+class ACE_Export ACE_LSOCK_Dgram : public ACE_SOCK_Dgram, public ACE_LSOCK
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_LSOCK_Dgram (void);
+
+ /// Initiate a local dgram.
+ ACE_LSOCK_Dgram (const ACE_Addr &local,
+ int protocol_family = PF_UNIX,
+ int protocol = 0);
+
+ /// Initiate a local dgram.
+ int open (const ACE_Addr &local,
+ int protocol_family = PF_UNIX,
+ int protocol = 0);
+
+ /// Get handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Set handle.
+ void set_handle (ACE_HANDLE);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Dgram.i"
+#endif
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_DGRAM_H */
diff --git a/ace/Sockets/LSOCK_Dgram.i b/ace/Sockets/LSOCK_Dgram.i
new file mode 100644
index 00000000000..ffc1890d12b
--- /dev/null
+++ b/ace/Sockets/LSOCK_Dgram.i
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+// $Id$
+
+// LSOCK_Dgram.i
+
+ASYS_INLINE void
+ACE_LSOCK_Dgram::set_handle (ACE_HANDLE h)
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::set_handle");
+ this->ACE_SOCK_Dgram::set_handle (h);
+ this->ACE_LSOCK::set_handle (h);
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_LSOCK_Dgram::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Dgram::get_handle");
+ return this->ACE_SOCK_Dgram::get_handle ();
+}
+
diff --git a/ace/Sockets/LSOCK_Stream.cpp b/ace/Sockets/LSOCK_Stream.cpp
new file mode 100644
index 00000000000..6cc8efdb20c
--- /dev/null
+++ b/ace/Sockets/LSOCK_Stream.cpp
@@ -0,0 +1,132 @@
+// LSOCK_Stream.cpp
+// $Id$
+
+#include "ace/LSOCK_Stream.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ace, LSOCK_Stream, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Stream.i"
+#endif
+
+ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Stream)
+
+int
+ACE_LSOCK_Stream::get_local_addr (ACE_Addr &addr) const
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::get_local_addr");
+
+ // Perform the downcast since <addr> had better be an
+ // <ACE_UNIX_Addr>.
+ ACE_UNIX_Addr *rhs_unix_addr = ACE_dynamic_cast (ACE_UNIX_Addr *, &addr);
+ ACE_UNIX_Addr lhs_unix_addr;
+
+ if (rhs_unix_addr == 0)
+ return -1;
+ else if (ACE_SOCK::get_local_addr (lhs_unix_addr) == -1)
+ return -1;
+ else
+ {
+ *rhs_unix_addr = lhs_unix_addr;
+ return 0;
+ }
+}
+
+int
+ACE_LSOCK_Stream::get_remote_addr (ACE_Addr &addr) const
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::get_remote_addr");
+
+ return this->get_local_addr (addr);
+}
+
+void
+ACE_LSOCK_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_SOCK_Stream::dump ();
+ ACE_LSOCK::dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+#if defined (ACE_HAS_MSG)
+
+// Send a readv-style vector of buffers, along with an open I/O
+// handle.
+
+ssize_t
+ACE_LSOCK_Stream::send_msg (const iovec iov[],
+ size_t n,
+ ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::send_msg");
+ msghdr send_msg;
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ char cmsgbuf[ACE_BSD_CONTROL_MSG_LEN];
+ cmsghdr *cmsgptr = (cmsghdr *) cmsgbuf;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ send_msg.msg_iov = (iovec *) iov;
+ send_msg.msg_iovlen = n;
+ send_msg.msg_name = 0;
+ send_msg.msg_namelen = 0;
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ cmsgptr->cmsg_level = SOL_SOCKET;
+ cmsgptr->cmsg_type = SCM_RIGHTS;
+ cmsgptr->cmsg_len = sizeof cmsgbuf;
+ send_msg.msg_control = cmsgbuf;
+ send_msg.msg_controllen = sizeof cmsgbuf;
+ *(ACE_HANDLE *) CMSG_DATA (cmsgptr) = handle;
+ send_msg.msg_flags = 0 ;
+#else
+ send_msg.msg_accrights = (char *) &handle;
+ send_msg.msg_accrightslen = sizeof handle;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ return ACE_OS::sendmsg (this->ACE_SOCK_Stream::get_handle (),
+ &send_msg, 0);
+}
+
+// Read a readv-style vector of buffers, along with an open I/O
+// handle.
+
+ssize_t
+ACE_LSOCK_Stream::recv_msg (iovec iov[],
+ size_t n,
+ ACE_HANDLE &handle)
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::recv_msg");
+ msghdr recv_msg;
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ char cmsgbuf[ACE_BSD_CONTROL_MSG_LEN];
+ cmsghdr *cmsgptr = (cmsghdr *) cmsgbuf;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ recv_msg.msg_iov = (iovec *) iov;
+ recv_msg.msg_iovlen = n;
+ recv_msg.msg_name = 0;
+ recv_msg.msg_namelen = 0;
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ recv_msg.msg_control = cmsgbuf;
+ recv_msg.msg_controllen = sizeof cmsgbuf;
+ ssize_t result = ACE_OS::recvmsg (this->ACE_SOCK_Stream::get_handle (),
+ &recv_msg, 0);
+ handle = *(ACE_HANDLE*) CMSG_DATA (cmsgptr) ;
+ return result;
+#else
+ recv_msg.msg_accrights = (char *) &handle;
+ recv_msg.msg_accrightslen = sizeof handle;
+
+ return ACE_OS::recvmsg (this->ACE_SOCK_Stream::get_handle (),
+ &recv_msg, 0);
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+}
+#endif /* ACE_HAS_MSG */
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ace/Sockets/LSOCK_Stream.h b/ace/Sockets/LSOCK_Stream.h
new file mode 100644
index 00000000000..51382e2f5dd
--- /dev/null
+++ b/ace/Sockets/LSOCK_Stream.h
@@ -0,0 +1,77 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file LSOCK_Stream.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_LOCAL_SOCK_STREAM_H
+#define ACE_LOCAL_SOCK_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+/**
+ * @class ACE_LSOCK_Stream
+ *
+ * @brief Create a Local ACE_SOCK stream.
+ */
+class ACE_Export ACE_LSOCK_Stream : public ACE_SOCK_Stream, public ACE_LSOCK
+{
+public:
+ // = Send/recv methods.
+ /// Send iovecs via <::writev>.
+ ssize_t send_msg (const iovec iov[],
+ size_t n,
+ ACE_HANDLE handle);
+
+ /// Send iovecs via <::writev>.
+ ssize_t recv_msg (iovec iov[],
+ size_t n,
+ ACE_HANDLE &handle);
+
+ /// Get handle.
+ ACE_HANDLE get_handle (void) const;
+
+ /// Overrides set_handle from the base classes.
+ void set_handle (ACE_HANDLE fd);
+
+ // = Meta-type info
+ typedef ACE_UNIX_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// This method simply returns the "local" addr.
+ int get_local_addr (ACE_Addr &) const;
+
+ /// This method returns the "local" addr since it's the same value
+ /// for UNIX domain sockets.
+ int get_remote_addr (ACE_Addr &) const;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/LSOCK_Stream.i"
+#endif
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#include "ace/post.h"
+#endif /* ACE_LOCAL_SOCK_STREAM_H */
diff --git a/ace/Sockets/LSOCK_Stream.i b/ace/Sockets/LSOCK_Stream.i
new file mode 100644
index 00000000000..6ee0a6f90c7
--- /dev/null
+++ b/ace/Sockets/LSOCK_Stream.i
@@ -0,0 +1,25 @@
+/* -*- C++ -*- */
+// $Id$
+
+// LSOCK_Stream.i
+
+// Sets both the file descriptors... Overrides handle from the base
+// classes.
+
+ASYS_INLINE void
+ACE_LSOCK_Stream::set_handle (ACE_HANDLE fd)
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::set_handle");
+ this->ACE_SOCK_Stream::set_handle (fd);
+ this->ACE_LSOCK::set_handle (fd);
+}
+
+ASYS_INLINE ACE_HANDLE
+ACE_LSOCK_Stream::get_handle (void) const
+{
+ ACE_TRACE ("ACE_LSOCK_Stream::get_handle");
+ return this->ACE_SOCK_Stream::get_handle ();
+}
+
+
+
diff --git a/ace/Sockets/SOCK.cpp b/ace/Sockets/SOCK.cpp
new file mode 100644
index 00000000000..333ff6c16b5
--- /dev/null
+++ b/ace/Sockets/SOCK.cpp
@@ -0,0 +1,182 @@
+// SOCK.cpp
+// $Id$
+
+#include "ace/SOCK.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK.i"
+#endif
+
+ACE_RCSID(ace, SOCK, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK)
+
+void
+ACE_SOCK::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK::dump");
+}
+
+ACE_SOCK::ACE_SOCK (void)
+{
+ // ACE_TRACE ("ACE_SOCK::ACE_SOCK");
+}
+
+// Returns information about the remote peer endpoint (if there is
+// one).
+
+int
+ACE_SOCK::get_remote_addr (ACE_Addr &sa) const
+{
+ ACE_TRACE ("ACE_SOCK::get_remote_addr");
+
+ int len = sa.get_size ();
+ sockaddr *addr = ACE_reinterpret_cast (sockaddr *,
+ sa.get_addr ());
+
+ if (ACE_OS::getpeername (this->get_handle (),
+ addr,
+ &len) == -1)
+ return -1;
+
+ sa.set_size (len);
+ sa.set_type (addr->sa_family);
+ return 0;
+}
+
+int
+ACE_SOCK::get_local_addr (ACE_Addr &sa) const
+{
+ ACE_TRACE ("ACE_SOCK::get_local_addr");
+
+ int len = sa.get_size ();
+ sockaddr *addr = ACE_reinterpret_cast (sockaddr *,
+ sa.get_addr ());
+
+ if (ACE_OS::getsockname (this->get_handle (),
+ addr,
+ &len) == -1)
+ return -1;
+
+ sa.set_type (addr->sa_family);
+ sa.set_size (len);
+ return 0;
+}
+
+// Close down a ACE_SOCK.
+
+int
+ACE_SOCK::close (void)
+{
+ ACE_TRACE ("ACE_SOCK::close");
+ int result = 0;
+
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ {
+ result = ACE_OS::closesocket (this->get_handle ());
+ this->set_handle (ACE_INVALID_HANDLE);
+ }
+ return result;
+}
+
+int
+ACE_SOCK::open (int type,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK::open");
+ int one = 1;
+
+ this->set_handle (ACE_OS::socket (protocol_family,
+ type,
+ protocol));
+
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ return -1;
+ else if (protocol_family != PF_UNIX
+ && reuse_addr
+ && this->set_option (SOL_SOCKET,
+ SO_REUSEADDR,
+ &one,
+ sizeof one) == -1)
+ {
+ this->close ();
+ return -1;
+ }
+ return 0;
+}
+
+// General purpose constructor for performing server ACE_SOCK
+// creation.
+
+ACE_SOCK::ACE_SOCK (int type,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ // ACE_TRACE ("ACE_SOCK::ACE_SOCK");
+ if (this->open (type,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK::ACE_SOCK")));
+}
+
+int
+ACE_SOCK::open (int type,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK::open");
+
+ this->set_handle (ACE_OS::socket (protocol_family,
+ type,
+ protocol,
+ protocolinfo,
+ g,
+ flags));
+ int one = 1;
+
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ return -1;
+ else if (reuse_addr
+ && this->set_option (SOL_SOCKET,
+ SO_REUSEADDR,
+ &one,
+ sizeof one) == -1)
+ {
+ this->close ();
+ return -1;
+ }
+ else
+ return 0;
+}
+
+ACE_SOCK::ACE_SOCK (int type,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ // ACE_TRACE ("ACE_SOCK::ACE_SOCK");
+ if (this->open (type,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK::ACE_SOCK")));
+}
diff --git a/ace/Sockets/SOCK.h b/ace/Sockets/SOCK.h
new file mode 100644
index 00000000000..bbed708afe0
--- /dev/null
+++ b/ace/Sockets/SOCK.h
@@ -0,0 +1,120 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_H
+#define ACE_SOCK_H
+#include "ace/pre.h"
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+#include "ace/IPC_SAP.h"
+
+/**
+ * @class ACE_SOCK
+ *
+ * @brief An abstract class that forms the basis for more specific
+ * classes, such as <ACE_SOCK_Acceptor> and <ACE_SOCK_Stream>.
+ * Do not instantiate this class.
+ *
+ * This class provides functions that are common to all of the
+ * <ACE_SOCK_*> classes. <ACE_SOCK> provides the ability to get
+ * and set socket options, get the local and remote addresses,
+ * and open and close a socket handle.
+ */
+class ACE_Export ACE_SOCK : public ACE_IPC_SAP
+{
+public:
+ /// Default ctor/dtor.
+ ~ACE_SOCK (void);
+
+ /// Wrapper around the <setsockopt> system call.
+ int set_option (int level,
+ int option,
+ void *optval,
+ int optlen) const;
+
+ /// Wrapper around the <getsockopt> system call.
+ int get_option (int level,
+ int option,
+ void *optval,
+ int *optlen) const;
+
+ /// Close down the socket handle.
+ int close (void);
+
+ /// Return the local endpoint address in the referenced <ACE_Addr>.
+ /// Returns 0 if successful, else -1.
+ int get_local_addr (ACE_Addr &) const;
+
+ /**
+ * Return the address of the remotely connected peer (if there is
+ * one), in the referenced <ACE_Addr>. Returns 0 if successful, else
+ * -1.
+ */
+ int get_remote_addr (ACE_Addr &) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Wrapper around the BSD-style <socket> system call (no QoS).
+ int open (int type,
+ int protocol_family,
+ int protocol,
+ int reuse_addr);
+
+ /// Wrapper around the QoS-enabled <WSASocket> function.
+ int open (int type,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr);
+
+protected:
+ /// Constructor with arguments to call the BSD-style <socket> system
+ /// call (no QoS).
+ ACE_SOCK (int type,
+ int protocol_family,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /// Constructor with arguments to call the QoS-enabled <WSASocket>
+ /// function.
+ ACE_SOCK (int type,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr);
+
+ /// Default constructor is protected to prevent instances of this class
+ /// from being defined.
+ ACE_SOCK (void);
+
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_H */
diff --git a/ace/Sockets/SOCK.i b/ace/Sockets/SOCK.i
new file mode 100644
index 00000000000..78b17d3e36e
--- /dev/null
+++ b/ace/Sockets/SOCK.i
@@ -0,0 +1,34 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK.i
+
+ASYS_INLINE
+ACE_SOCK::~ACE_SOCK (void)
+{
+ // ACE_TRACE ("ACE_SOCK::~ACE_SOCK");
+}
+
+ASYS_INLINE int
+ACE_SOCK::set_option (int level,
+ int option,
+ void *optval,
+ int optlen) const
+{
+ ACE_TRACE ("ACE_SOCK::set_option");
+ return ACE_OS::setsockopt (this->get_handle (), level,
+ option, (char *) optval, optlen);
+}
+
+// Provides access to the ACE_OS::getsockopt system call.
+
+ASYS_INLINE int
+ACE_SOCK::get_option (int level,
+ int option,
+ void *optval,
+ int *optlen) const
+{
+ ACE_TRACE ("ACE_SOCK::get_option");
+ return ACE_OS::getsockopt (this->get_handle (), level,
+ option, (char *) optval, optlen);
+}
diff --git a/ace/Sockets/SOCK_Acceptor.cpp b/ace/Sockets/SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..d92f9343447
--- /dev/null
+++ b/ace/Sockets/SOCK_Acceptor.cpp
@@ -0,0 +1,398 @@
+// SOCK_Acceptor.cpp
+// $Id$
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_QoS.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Acceptor.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/Synch.h"
+
+ACE_RCSID(ace, SOCK_Acceptor, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Acceptor)
+
+// Do nothing routine for constructor.
+
+ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor");
+}
+
+// Performs the timed accept operation.
+
+int
+ACE_SOCK_Acceptor::shared_accept_start (ACE_Time_Value *timeout,
+ int restart,
+ int &in_blocking_mode) const
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::shared_accept_start");
+
+ ACE_HANDLE handle = this->get_handle ();
+
+ // Handle the case where we're doing a timed <accept>.
+ if (timeout != 0)
+ {
+ if (ACE::handle_timed_accept (handle,
+ timeout,
+ restart) == -1)
+ return -1;
+ else
+ {
+ in_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle),
+ ACE_NONBLOCK);
+ // Set the handle into non-blocking mode if it's not already
+ // in it.
+ if (in_blocking_mode
+ && ACE::set_flags (handle,
+ ACE_NONBLOCK) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_SOCK_Acceptor::shared_accept_finish (ACE_SOCK_Stream new_stream,
+ int in_blocking_mode,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::shared_accept_finish ()");
+
+ ACE_HANDLE new_handle = new_stream.get_handle ();
+
+ // Check to see if we were originally in blocking mode, and if so,
+ // set the <new_stream>'s handle and <this> handle to be in blocking
+ // mode.
+ if (in_blocking_mode)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ // Only disable ACE_NONBLOCK if we weren't in non-blocking mode
+ // originally.
+ ACE::clr_flags (this->get_handle (),
+ ACE_NONBLOCK);
+ ACE::clr_flags (new_handle,
+ ACE_NONBLOCK);
+ }
+
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ if (reset_new_handle)
+ // Reset the event association inherited by the new handle.
+ ::WSAEventSelect ((SOCKET) new_handle, 0, 0);
+#else
+ ACE_UNUSED_ARG (reset_new_handle);
+#endif /* ACE_WIN32 */
+
+ return new_handle == ACE_INVALID_HANDLE ? -1 : 0;
+}
+
+// General purpose routine for accepting new connections.
+
+int
+ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::accept");
+
+ int in_blocking_mode = 0;
+ if (this->shared_accept_start (timeout,
+ restart,
+ in_blocking_mode) == -1)
+ return -1;
+ else
+ {
+ // On Win32 the third parameter to <accept> must be a NULL
+ // pointer if we want to ignore the client's address.
+ int *len_ptr = 0;
+ sockaddr *addr = 0;
+ int len = 0;
+
+ if (remote_addr != 0)
+ {
+ len = remote_addr->get_size ();
+ len_ptr = &len;
+ addr = (sockaddr *) remote_addr->get_addr ();
+ }
+
+ do
+ new_stream.set_handle (ACE_OS::accept (this->get_handle (),
+ addr,
+ len_ptr));
+ while (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && restart != 0
+ && errno == EINTR
+ && timeout == 0);
+
+ // Reset the size of the addr, so the proper UNIX/IPv4/IPv6 family
+ // is known.
+ if (new_stream.get_handle () != ACE_INVALID_HANDLE
+ && remote_addr != 0)
+ {
+ remote_addr->set_size (len);
+ remote_addr->set_type (addr->sa_family);
+ }
+ }
+
+ return this->shared_accept_finish (new_stream,
+ in_blocking_mode,
+ reset_new_handle);
+}
+
+int
+ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream,
+ ACE_Accept_QoS_Params qos_params,
+ ACE_Addr *remote_addr,
+ ACE_Time_Value *timeout,
+ int restart,
+ int reset_new_handle) const
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::accept");
+
+ int in_blocking_mode = 0;
+ if (this->shared_accept_start (timeout,
+ restart,
+ in_blocking_mode) == -1)
+ return -1;
+ else
+ {
+ // On Win32 the third parameter to <accept> must be a NULL
+ // pointer if we want to ignore the client's address.
+ int *len_ptr = 0;
+ int len = 0;
+ sockaddr *addr = 0;
+
+ if (remote_addr != 0)
+ {
+ len = remote_addr->get_size ();
+ len_ptr = &len;
+ addr = (sockaddr *) remote_addr->get_addr ();
+ }
+
+ do
+ new_stream.set_handle (ACE_OS::accept (this->get_handle (),
+ addr,
+ len_ptr,
+ qos_params));
+ while (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && restart != 0
+ && errno == EINTR
+ && timeout == 0);
+
+ // Reset the size of the addr, which is only necessary for UNIX
+ // domain sockets.
+ if (new_stream.get_handle () != ACE_INVALID_HANDLE
+ && remote_addr != 0)
+ remote_addr->set_size (len);
+ }
+
+ return this->shared_accept_finish (new_stream,
+ in_blocking_mode,
+ reset_new_handle);
+}
+
+void
+ACE_SOCK_Acceptor::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::dump");
+}
+
+int
+ACE_SOCK_Acceptor::shared_open (const ACE_Addr &local_sap,
+ int protocol_family,
+ int backlog)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::shared_open");
+ int error = 0;
+
+#if defined (ACE_HAS_IPV6)
+ ACE_ASSERT (protocol_family == PF_INET || protocol_family == PF_INET6);
+
+ if (protocol_family == PF_INET6)
+ {
+ sockaddr_in6 local_inet6_addr;
+ ACE_OS::memset (ACE_reinterpret_cast (void *,
+ &local_inet6_addr),
+ 0,
+ sizeof local_inet6_addr);
+
+ if (local_sap == ACE_Addr::sap_any)
+ {
+ local_inet6_addr.sin6_family = AF_INET6;
+ local_inet6_addr.sin6_port = 0;
+ local_inet6_addr.sin6_addr = in6addr_any;
+ }
+ else
+ local_inet6_addr = *ACE_reinterpret_cast (sockaddr_in6 *,
+ local_sap.get_addr ());
+
+ // We probably don't need a bind_port written here.
+ // There are currently no supported OS's that define
+ // ACE_LACKS_WILDCARD_BIND.
+ if (ACE_OS::bind (this->get_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ &local_inet6_addr),
+ sizeof local_inet6_addr) == -1)
+ error = 1;
+ }
+ else
+#endif
+ if (protocol_family == PF_INET)
+ {
+ sockaddr_in local_inet_addr;
+ ACE_OS::memset (ACE_reinterpret_cast (void *,
+ &local_inet_addr),
+ 0,
+ sizeof local_inet_addr);
+
+ if (local_sap == ACE_Addr::sap_any)
+ {
+ local_inet_addr.sin_port = 0;
+ }
+ else
+ local_inet_addr = *ACE_reinterpret_cast (sockaddr_in *,
+ local_sap.get_addr ());
+ if (local_inet_addr.sin_port == 0)
+ {
+ if (ACE::bind_port (this->get_handle ()) == -1)
+ error = 1;
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ &local_inet_addr),
+ sizeof local_inet_addr) == -1)
+ error = 1;
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ (sockaddr *) local_sap.get_addr (),
+ local_sap.get_size ()) == -1)
+ error = 1;
+
+ if (error != 0
+ || ACE_OS::listen (this->get_handle (),
+ backlog) == -1)
+ {
+ error = 1;
+ this->close ();
+ }
+
+ return error ? -1 : 0;
+}
+
+int
+ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::open");
+
+ if (protocol_family == PF_UNSPEC)
+ protocol_family = local_sap.get_type ();
+
+ if (ACE_SOCK::open (SOCK_STREAM,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return this->shared_open (local_sap,
+ protocol_family,
+ backlog);
+}
+
+ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor");
+ if (this->open (local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Acceptor")));
+}
+
+// General purpose routine for performing server ACE_SOCK creation.
+
+int
+ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::open");
+
+ if (local_sap != ACE_Addr::sap_any)
+ protocol_family = local_sap.get_type ();
+ else if (protocol_family == PF_UNSPEC)
+ {
+#if defined (ACE_HAS_IPV6)
+ protocol_family = ACE_Sock_Connect::ipv6_enabled () ? PF_INET6 : PF_INET;
+#else
+ protocol_family = PF_INET;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+ if (ACE_SOCK::open (SOCK_STREAM,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return this->shared_open (local_sap,
+ protocol_family,
+ backlog);
+}
+
+// General purpose routine for performing server ACE_SOCK creation.
+
+ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr,
+ int protocol_family,
+ int backlog,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor");
+ if (this->open (local_sap,
+ reuse_addr,
+ protocol_family,
+ backlog,
+ protocol) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Acceptor")));
+}
+
+int
+ACE_SOCK_Acceptor::close (void)
+{
+ return ACE_SOCK::close ();
+}
diff --git a/ace/Sockets/SOCK_Acceptor.h b/ace/Sockets/SOCK_Acceptor.h
new file mode 100644
index 00000000000..b5bd8f8ff17
--- /dev/null
+++ b/ace/Sockets/SOCK_Acceptor.h
@@ -0,0 +1,171 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Acceptor.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_ACCEPTOR_H
+#define ACE_SOCK_ACCEPTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+
+/**
+ * @class ACE_SOCK_Acceptor
+ *
+ * @brief Defines a factory that creates new <ACE_Stream>s passively.
+ *
+ * The <ACE_SOCK_Acceptor> has its own "passive-mode" socket.
+ * This serves as a factory to create so-called "data-mode"
+ * sockets, which are what the <ACE_SOCK_Stream> encapsulates.
+ * Therefore, by inheriting from <ACE_SOCK>, <ACE_SOCK_Acceptor>
+ * gets its very own socket.
+ */
+class ACE_Export ACE_SOCK_Acceptor : public ACE_SOCK
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Acceptor (void);
+
+ /**
+ * Initialize a passive-mode BSD-style acceptor socket (no QoS).
+ * <local_sap> is the address that we're going to listen for
+ * connections on. If <reuse_addr> is 1 then we'll use the
+ * <SO_REUSEADDR> to reuse this address.
+ */
+ ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Initialize a passive-mode QoS-enabled acceptor socket. Returns 0
+ /// on success and -1 on failure.
+ ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /**
+ * Initialize a passive-mode BSD-style acceptor socket (no QoS).
+ * <local_sap> is the address that we're going to listen for
+ * connections on. If <reuse_addr> is 1 then we'll use the
+ * <SO_REUSEADDR> to reuse this address. Returns 0 on success and
+ * -1 on failure.
+ */
+ int open (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Initialize a passive-mode QoS-enabled acceptor socket. Returns 0
+ /// on success and -1 on failure.
+ int open (const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int protocol_family = PF_UNSPEC,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+
+ /// Close the socket. Returns 0 on success and -1 on failure.
+ int close (void);
+
+ /// Default dtor.
+ ~ACE_SOCK_Acceptor (void);
+
+ // = Passive connection <accept> methods.
+ /**
+ * Accept a new <ACE_SOCK_Stream> connection. A <timeout> of 0
+ * means block forever, a <timeout> of {0, 0} means poll. <restart>
+ * == 1 means "restart if interrupted," i.e., if errno == EINTR.
+ * Note that <new_stream> inherits the "blocking mode" of <this>
+ * <ACE_SOCK_Acceptor>, i.e., if <this> acceptor factory is in
+ * non-blocking mode, the <net_stream> will be in non-blocking mode
+ * and vice versa.
+ */
+ int accept (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ /**
+ * Accept a new <ACE_SOCK_Stream> connection using the QoS
+ * information in <qos_params>. A <timeout> of 0 means block
+ * forever, a <timeout> of {0, 0} means poll. <restart> == 1 means
+ * "restart if interrupted," i.e., if errno == EINTR. Note that
+ * <new_stream> inherits the "blocking mode" of <this>
+ * <ACE_SOCK_Acceptor>, i.e., if <this> acceptor factory is in
+ * non-blocking mode, the <net_stream> will be in non-blocking mode
+ * and vice versa.
+ */
+ int accept (ACE_SOCK_Stream &new_stream,
+ ACE_Accept_QoS_Params qos_params,
+ ACE_Addr *remote_addr = 0,
+ ACE_Time_Value *timeout = 0,
+ int restart = 1,
+ int reset_new_handle = 0) const;
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+ typedef ACE_SOCK_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Perform operations that must occur before <ACE_OS::accept> is
+ /// called.
+ int shared_accept_start (ACE_Time_Value *timeout,
+ int restart,
+ int &in_blocking_mode) const;
+
+ /// Perform operations that must occur after <ACE_OS::accept> is
+ /// called.
+ int shared_accept_finish (ACE_SOCK_Stream new_stream,
+ int in_blocking_mode,
+ int reset_new_handle) const;
+
+ /**
+ * This method factors out the common <open> code and is called by
+ * both the QoS-enabled <open> method and the BSD-style <open>
+ * method.
+ */
+ int shared_open (const ACE_Addr &local_sap,
+ int protocol_family,
+ int backlog);
+
+private:
+ /// Do not allow this function to percolate up to this interface...
+ int get_remote_addr (ACE_Addr &) const;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Acceptor.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_ACCEPTOR_H */
diff --git a/ace/Sockets/SOCK_Acceptor.i b/ace/Sockets/SOCK_Acceptor.i
new file mode 100644
index 00000000000..0ba44700809
--- /dev/null
+++ b/ace/Sockets/SOCK_Acceptor.i
@@ -0,0 +1,12 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_Acceptor.i
+
+ASYS_INLINE
+ACE_SOCK_Acceptor::~ACE_SOCK_Acceptor (void)
+{
+ ACE_TRACE ("ACE_SOCK_Acceptor::~ACE_SOCK_Acceptor");
+}
+
+
diff --git a/ace/Sockets/SOCK_CODgram.cpp b/ace/Sockets/SOCK_CODgram.cpp
new file mode 100644
index 00000000000..217257158fe
--- /dev/null
+++ b/ace/Sockets/SOCK_CODgram.cpp
@@ -0,0 +1,106 @@
+// SOCK_CODgram.cpp
+// $Id$
+
+#include "ace/SOCK_CODgram.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_CODgram.i"
+#endif
+
+ACE_RCSID(ace, SOCK_CODgram, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_CODgram)
+
+void
+ACE_SOCK_CODgram::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::dump");
+}
+
+// Here's the general-purpose constructor.
+
+ACE_SOCK_CODgram::ACE_SOCK_CODgram (const ACE_Addr &remote, const ACE_Addr &local,
+ int protocol_family, int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::ACE_SOCK_CODgram");
+ if (this->open (remote, local,
+ protocol_family, protocol, reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("ACE_SOCK_CODgram")));
+}
+
+/* This is the general-purpose open routine. Note that it performs
+ a different set of functions depending on the LOCAL and REMOTE
+ addresses passed to it. Here's the basic logic:
+
+ 1. remote == ACE_Addr::sap_any && local == ACE_Addr::sap_any
+ if protocol_family == PF_INET then
+ bind the local address to a randomly generated port number...
+
+ 2. remote == ACE_Addr::sap_any && local != ACE_Addr::sap_any
+ we are just binding the local address
+ (used primarily by servers)
+
+ 3. remote != ACE_Addr::sap_any && local == ACE_Addr::sap_any
+ we are connecting to the remote address
+ (used primarily by clients)
+
+ 4. remote != ACE_Addr::sap_any && local != ACE_Addr::sap_any
+ we are binding to the local address
+ and connecting to the remote address
+*/
+
+int
+ACE_SOCK_CODgram::open (const ACE_Addr &remote, const ACE_Addr &local,
+ int protocol_family, int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::open");
+ if (ACE_SOCK::open (SOCK_DGRAM, protocol_family,
+ protocol, reuse_addr) == -1)
+ return -1;
+ else
+ {
+ int error = 0;
+
+ if (local == ACE_Addr::sap_any && remote == ACE_Addr::sap_any)
+ {
+ // Assign an arbitrary port number from the transient range!!
+
+ if (protocol_family == PF_INET
+ && ACE::bind_port (this->get_handle ()) == -1)
+ error = 1;
+ }
+ // We are binding just the local address.
+ else if (local != ACE_Addr::sap_any && remote == ACE_Addr::sap_any)
+ {
+ if (ACE_OS::bind (this->get_handle (), (sockaddr *) local.get_addr (),
+ local.get_size ()) == -1)
+ error = 1;
+ }
+ // We are connecting to the remote address.
+ else if (local == ACE_Addr::sap_any && remote != ACE_Addr::sap_any)
+ {
+ if (ACE_OS::connect (this->get_handle (), (sockaddr *) remote.get_addr (),
+ remote.get_size ()) == -1)
+ error = 1;
+ }
+ // We are binding to the local address and connecting to the
+ // remote addresses.
+ else
+ {
+ if (ACE_OS::bind (this->get_handle (), (sockaddr *) local.get_addr (),
+ local.get_size ()) == -1
+ || ACE_OS::connect (this->get_handle (), (sockaddr *) remote.get_addr (),
+ remote.get_size ()) == -1)
+ error = 1;
+ }
+ if (error)
+ {
+ this->close ();
+ this->set_handle (ACE_INVALID_HANDLE);
+ }
+ return error ? -1 : 0;
+ }
+}
diff --git a/ace/Sockets/SOCK_CODgram.h b/ace/Sockets/SOCK_CODgram.h
new file mode 100644
index 00000000000..e275a420031
--- /dev/null
+++ b/ace/Sockets/SOCK_CODgram.h
@@ -0,0 +1,70 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_CODgram.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SOCK_CODGRAM_H
+#define ACE_SOCK_CODGRAM_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_IO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+#include "ace/INET_Addr.h"
+
+/**
+ * @class ACE_SOCK_CODgram
+ *
+ * @brief Defines the member functions for the ACE_SOCK connected
+ * datagram abstraction.
+ */
+class ACE_Export ACE_SOCK_CODgram : public ACE_SOCK_IO
+{
+public:
+ // = Initialization methods.
+ /// Default constructor.
+ ACE_SOCK_CODgram (void);
+
+ ACE_SOCK_CODgram (const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /// Default dtor.
+ ~ACE_SOCK_CODgram (void);
+
+ // Initiate a connected dgram.
+
+ /// Initiate a connected dgram.
+ int open (const ACE_Addr &remote_sap,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_CODgram.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_CODGRAM_H */
diff --git a/ace/Sockets/SOCK_CODgram.i b/ace/Sockets/SOCK_CODgram.i
new file mode 100644
index 00000000000..7dd5b40a1d6
--- /dev/null
+++ b/ace/Sockets/SOCK_CODgram.i
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_CODgram.i
+
+ASYS_INLINE
+ACE_SOCK_CODgram::ACE_SOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::ACE_SOCK_CODgram");
+}
+
+ASYS_INLINE
+ACE_SOCK_CODgram::~ACE_SOCK_CODgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_CODgram::~ACE_SOCK_CODgram");
+}
+
+
diff --git a/ace/Sockets/SOCK_Connector.cpp b/ace/Sockets/SOCK_Connector.cpp
new file mode 100644
index 00000000000..6c77e856de6
--- /dev/null
+++ b/ace/Sockets/SOCK_Connector.cpp
@@ -0,0 +1,335 @@
+// SOCK_Connector.cpp
+// $Id$
+
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_QoS.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Connector.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, SOCK_Connector, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Connector)
+
+void
+ACE_SOCK_Connector::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Connector::dump");
+}
+
+int
+ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream &new_stream,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::shared_open");
+
+ // Only open a new socket if we don't already have a valid handle.
+ if (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && new_stream.open (SOCK_STREAM,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream &new_stream,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::shared_open");
+
+ // Only open a new socket if we don't already have a valid handle.
+ if (new_stream.get_handle () == ACE_INVALID_HANDLE
+ && new_stream.open (SOCK_STREAM,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_Connector::shared_connect_start (ACE_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::shared_connect_start");
+
+ if (local_sap != ACE_Addr::sap_any)
+ {
+ sockaddr *laddr = ACE_reinterpret_cast (sockaddr *,
+ local_sap.get_addr ());
+ size_t size = local_sap.get_size ();
+
+ if (ACE_OS::bind (new_stream.get_handle (),
+ laddr,
+ size) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_stream.close ();
+ return -1;
+ }
+ }
+
+ // Enable non-blocking, if required.
+ if (timeout != 0
+ && new_stream.enable (ACE_NONBLOCK) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_SOCK_Connector::shared_connect_finish (ACE_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout,
+ int result)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::shared_connect_finish");
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+
+ if (result == -1 && timeout != 0)
+ {
+ // Check whether the connection is in progress.
+ if (error == EINPROGRESS || error == EWOULDBLOCK)
+ {
+ // This expression checks if we were polling.
+ if (timeout->sec () == 0
+ && timeout->usec () == 0)
+ error = EWOULDBLOCK;
+ // Wait synchronously using timeout.
+ else if (this->complete (new_stream,
+ 0,
+ timeout) == -1)
+ error = errno;
+ else
+ return 0;
+ }
+ }
+
+ // EISCONN is treated specially since this routine may be used to
+ // check if we are already connected.
+ if (result != -1 || error == EISCONN)
+ // Start out with non-blocking disabled on the <new_stream>.
+ new_stream.disable (ACE_NONBLOCK);
+ else if (!(error == EWOULDBLOCK || error == ETIMEDOUT))
+ new_stream.close ();
+
+ return result;
+}
+
+// Actively connect and produce a new ACE_SOCK_Stream if things go well...
+
+int
+ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int /* flags */,
+ int /* perms */,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::connect");
+
+ // @@ Should remove this arg when IPv6 is merged...
+ ACE_UNUSED_ARG (protocol_family);
+ protocol_family = remote_sap.get_type ();
+ if (this->shared_open (new_stream,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else if (this->shared_connect_start (new_stream,
+ timeout,
+ local_sap) == -1)
+ return -1;
+
+ int result = ACE_OS::connect (new_stream.get_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ remote_sap.get_addr ()),
+ remote_sap.get_size ());
+
+ return this->shared_connect_finish (new_stream,
+ timeout,
+ result);
+}
+
+int
+ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_QoS_Params qos_params,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ ACE_Protocol_Info * protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int /* perms */,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::connect");
+
+ // @@ Should remove this arg when IPv6 is merged...
+ ACE_UNUSED_ARG (protocol_family);
+ protocol_family = remote_sap.get_type ();
+
+ if (this->shared_open (new_stream,
+ remote_sap.get_type (),
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else if (this->shared_connect_start (new_stream,
+ timeout,
+ local_sap) == -1)
+ return -1;
+
+ int result = ACE_OS::connect (new_stream.get_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ remote_sap.get_addr ()),
+ remote_sap.get_size (),
+ qos_params);
+
+ return this->shared_connect_finish (new_stream,
+ timeout,
+ result);
+}
+
+// Try to complete a non-blocking connection.
+
+int
+ACE_SOCK_Connector::complete (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_sap,
+ const ACE_Time_Value *tv)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::complete");
+ ACE_HANDLE h = ACE::handle_timed_complete (new_stream.get_handle (),
+ tv);
+ // We failed to get connected.
+ if (h == ACE_INVALID_HANDLE)
+ {
+#if defined (ACE_WIN32)
+ // Win32 has a timing problem - if you check to see if the
+ // connection has completed too fast, it will fail - so wait
+ // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
+ // then retry to see if it's a real failure.
+ ACE_Time_Value time (0, ACE_NON_BLOCKING_BUG_DELAY);
+ ACE_OS::sleep (time);
+ h = ACE::handle_timed_complete (new_stream.get_handle (),
+ tv);
+ if (h == ACE_INVALID_HANDLE)
+ {
+#endif /* ACE_WIN32 */
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_stream.close ();
+ return -1;
+#if defined (ACE_WIN32)
+ }
+#endif /* ACE_WIN32 */
+ }
+
+ if (remote_sap != 0)
+ {
+ int len = remote_sap->get_size ();
+ sockaddr *addr = ACE_reinterpret_cast (sockaddr *,
+ remote_sap->get_addr ());
+ if (ACE_OS::getpeername (h,
+ addr,
+ &len) == -1)
+ {
+ // Save/restore errno.
+ ACE_Errno_Guard error (errno);
+ new_stream.close ();
+ return -1;
+ }
+ }
+
+ // Start out with non-blocking disabled on the <new_stream>.
+ new_stream.disable (ACE_NONBLOCK);
+ return 0;
+}
+
+ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ int reuse_addr,
+ int flags,
+ int perms,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
+
+ if (this->connect (new_stream,
+ remote_sap,
+ timeout,
+ local_sap,
+ reuse_addr,
+ flags,
+ perms,
+ protocol_family,
+ protocol) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
+}
+
+ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_QoS_Params qos_params,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr,
+ int perms,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
+
+ if (this->connect (new_stream,
+ remote_sap,
+ qos_params,
+ timeout,
+ local_sap,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr,
+ perms,
+ protocol_family,
+ protocol) == -1
+ && timeout != 0
+ && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
+}
diff --git a/ace/Sockets/SOCK_Connector.h b/ace/Sockets/SOCK_Connector.h
new file mode 100644
index 00000000000..1236c53eb92
--- /dev/null
+++ b/ace/Sockets/SOCK_Connector.h
@@ -0,0 +1,236 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Connector.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_CONNECTOR_H
+#define ACE_SOCK_CONNECTOR_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Time_Value.h"
+
+/**
+ * @class ACE_SOCK_Connector
+ *
+ * @brief Defines a factory that creates new <ACE_Stream>s actively.
+ *
+ * The <ACE_SOCK_Connector> doesn't have a socket of its own,
+ * i.e., it simply "borrows" the one from the ACE_SOCK_Stream
+ * that's being connected. The reason for this is that the
+ * underlying socket API doesn't use a "factory" socket to connect
+ * "data-mode" sockets. Therefore, there's no need to inherit
+ * <ACE_SOCK_Connector> from <ACE_SOCK>. A nice side-effect of
+ * this is that <ACE_SOCK_Connector>'s do not store state so they
+ * can be used reentrantly in multi-threaded programs.
+ */
+class ACE_Export ACE_SOCK_Connector
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Connector (void);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out; if the
+ * time expires before the connection is made <errno == ETIME>. Note
+ * the difference between this case and when a blocking connect
+ * is attmpted that TCP times out - in the latter case, errno will
+ * be ETIMEDOUT.
+ * The <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * The <protocol_family> and <protocol> parameters are passed down
+ * to the <socket> call, whereas <flags> and <perms> are ignored.
+ */
+ ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <qos_params> contains QoS parameters that are passed
+ * to the IntServ (RSVP) and DiffServ protocols. The <timeout> is
+ * the amount of time to wait to connect. If it's 0 then we block
+ * indefinitely. If *timeout == {0, 0} then the connection is done
+ * using non-blocking mode. In this case, if the connection can't
+ * be made immediately the value of -1 is returned with <errno ==
+ * EWOULDBLOCK>. If *timeout > {0, 0} then this is the amount of
+ * time to wait before timing out; if the time expires before the
+ * connection is made <errno == ETIME>. Note the difference between
+ * this case and when a blocking connect is attmpted that TCP times
+ * out - in the latter case, errno will be ETIMEDOUT.
+ * The <local_sap> is the value of local address to bind to. If
+ * it's the default value of <ACE_Addr::sap_any> then the user is
+ * letting the OS do the binding.
+ * If <reuse_addr> == 1 then the <local_addr> is reused,
+ * even if it hasn't been cleaned up yet.
+ * The <protocol_family> and <protocol> parameters are passed down
+ * to the <socket> call, whereas <flags> and <perms> are ignored.
+ */
+ ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_QoS_Params qos_params,
+ const ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ ACE_Protocol_Info *protocolinfo = 0,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ int reuse_addr = 0,
+ int perms = 0,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <timeout> is the amount of time to wait to connect.
+ * If it's 0 then we block indefinitely. If *timeout == {0, 0} then
+ * the connection is done using non-blocking mode. In this case, if
+ * the connection can't be made immediately the value of -1 is
+ * returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then
+ * this is the maximum amount of time to wait before timing out; if the
+ * time expires before the connection is made <errno == ETIME>. Note
+ * the difference between this case and when a blocking connect
+ * is attmpted that TCP times out - in the latter case, errno will
+ * be ETIMEDOUT.
+ * The <local_sap> is the value of local address to bind to. If it's
+ * the default value of <ACE_Addr::sap_any> then the user is letting
+ * the OS do the binding. If <reuse_addr> == 1 then the
+ * <local_addr> is reused, even if it hasn't been cleanedup yet.
+ * Note that the <new_stream> always starts out in blocking mode.
+ * The <protocol_family> and <protocol> parameters are passed down
+ * to the <socket> call, whereas <flags> and <perms> are ignored.
+ */
+ int connect (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ const ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ int reuse_addr = 0,
+ int flags = 0,
+ int perms = 0,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0);
+
+ /**
+ * Actively connect and produce a <new_stream> if things go well.
+ * The <remote_sap> is the address that we are trying to connect
+ * with. The <qos_params> contains QoS parameters that are passed
+ * to the IntServ (RSVP) and DiffServ protocols. The <timeout> is
+ * the amount of time to wait to connect. If it's 0 then we block
+ * indefinitely. If *timeout == {0, 0} then the connection is done
+ * using non-blocking mode. In this case, if the connection can't
+ * be made immediately the value of -1 is returned with <errno ==
+ * EWOULDBLOCK>. If *timeout > {0, 0} then this is the amount of
+ * time to wait before timing out; if the time expires before the
+ * connection is made <errno == ETIME>. Note the difference between
+ * this case and when a blocking connect is attmpted that TCP times
+ * out - in the latter case, errno will be ETIMEDOUT.
+ * The <local_sap> is the value of local address to bind to. If
+ * it's the default value of <ACE_Addr::sap_any> then the user is
+ * letting the OS do the binding.
+ * If <reuse_addr> == 1 then the <local_addr> is reused,
+ * even if it hasn't been cleanedup yet.
+ */
+ int connect (ACE_SOCK_Stream &new_stream,
+ const ACE_Addr &remote_sap,
+ ACE_QoS_Params qos_params,
+ const ACE_Time_Value *timeout = 0,
+ const ACE_Addr &local_sap = ACE_Addr::sap_any,
+ ACE_Protocol_Info *protocolinfo = 0,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ int reuse_addr = 0,
+ int perms = 0,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0);
+
+ /// Default dtor.
+ ~ACE_SOCK_Connector (void);
+
+ // = Completion routine.
+ /**
+ * Try to complete a non-blocking connection.
+ * If connection completion is successful then <new_stream> contains
+ * the connected ACE_SOCK_Stream. If <remote_sap> is non-NULL then it
+ * will contain the address of the connected peer.
+ */
+ int complete (ACE_SOCK_Stream &new_stream,
+ ACE_Addr *remote_sap = 0,
+ const ACE_Time_Value *timeout = 0);
+
+ /// Resets any event associations on this handle
+ int reset_new_handle (ACE_HANDLE handle);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+ typedef ACE_SOCK_Stream PEER_STREAM;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Perform operations that ensure the socket is opened using
+ /// BSD-style semantics (no QoS).
+ int shared_open (ACE_SOCK_Stream &new_stream,
+ int protocol_family,
+ int protocol,
+ int reuse_addr);
+
+ /// Perform operations that ensure the socket is opened using
+ /// QoS-enabled semantics.
+ int shared_open (ACE_SOCK_Stream &new_stream,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr);
+
+ /// Perform operations that must be called before <ACE_OS::connect>.
+ int shared_connect_start (ACE_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout,
+ const ACE_Addr &local_sap);
+
+ /// Perform operations that must be called after <ACE_OS::connect>.
+ int shared_connect_finish (ACE_SOCK_Stream &new_stream,
+ const ACE_Time_Value *timeout,
+ int result);
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Connector.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_CONNECTOR_H */
diff --git a/ace/Sockets/SOCK_Connector.i b/ace/Sockets/SOCK_Connector.i
new file mode 100644
index 00000000000..82b5e3e1739
--- /dev/null
+++ b/ace/Sockets/SOCK_Connector.i
@@ -0,0 +1,35 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_Connector.i
+
+// This constructor is used by a client when it wants to connect to
+// the specified REMOTE_SAP address using a blocking open.
+
+ASYS_INLINE
+ACE_SOCK_Connector::~ACE_SOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::~ACE_SOCK_Connector");
+}
+
+// Do-nothing constructor...
+
+ASYS_INLINE
+ACE_SOCK_Connector::ACE_SOCK_Connector (void)
+{
+ ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
+}
+
+ASYS_INLINE int
+ACE_SOCK_Connector::reset_new_handle (ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ // Reset the event association
+ return ::WSAEventSelect ((SOCKET) handle,
+ NULL,
+ 0);
+#else /* !defined ACE_HAS_WINSOCK2 */
+ ACE_UNUSED_ARG (handle);
+ return 0;
+#endif /* ACE_WIN32 */
+}
diff --git a/ace/Sockets/SOCK_Dgram.cpp b/ace/Sockets/SOCK_Dgram.cpp
new file mode 100644
index 00000000000..741ad75f44e
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram.cpp
@@ -0,0 +1,513 @@
+// SOCK_Dgram.cpp
+// $Id$
+
+#include "ace/SOCK_Dgram.h"
+#include "ace/Handle_Set.h"
+#include "ace/Synch.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram.i"
+#endif
+
+ACE_RCSID(ace, SOCK_Dgram, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram)
+
+void
+ACE_SOCK_Dgram::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::dump");
+}
+
+// Allows a client to read from a socket without having to provide a
+// buffer to read. This method determines how much data is in the
+// socket, allocates a buffer of this size, reads in the data, and
+// returns the number of bytes read.
+
+ssize_t
+ACE_SOCK_Dgram::recv (iovec io_vec[],
+ ACE_Addr &addr,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+#if defined (FIONREAD)
+ ACE_Handle_Set handle_set;
+ handle_set.reset ();
+ handle_set.set_bit (this->get_handle ());
+
+ // Check the status of the current socket to make sure there's data
+ // to recv (or time out).
+ switch (ACE_OS::select (int (this->get_handle ()) + 1,
+ handle_set,
+ 0, 0,
+ timeout))
+ {
+ case -1:
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ errno = ETIME;
+ return -1;
+ /* NOTREACHED */
+ default:
+ // Goes fine, fallthrough to get data
+ break;
+ }
+
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ int addr_len = addr.get_size ();
+ u_long inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD, (u_long *) &inlen) == -1)
+ return -1;
+ else if (inlen > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[inlen],
+ -1);
+ io_vec->iov_len = ACE_OS::recvfrom (this->get_handle (),
+ (char *) io_vec->iov_base,
+ inlen,
+ flags,
+ (sockaddr *) saddr,
+ &addr_len);
+ addr.set_size (addr_len);
+ return io_vec->iov_len;
+ }
+ else
+ return 0;
+#else
+ ACE_UNUSED_ARG (flags);
+ ACE_UNUSED_ARG (addr);
+ ACE_UNUSED_ARG (io_vec);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* FIONREAD */
+}
+
+// Here's the shared open function. Note that if we are using the
+// PF_INET protocol family and the address of LOCAL == the address of
+// the special variable SAP_ANY then we are going to arbitrarily bind
+// to a portnumber.
+
+int
+ACE_SOCK_Dgram::shared_open (const ACE_Addr &local,
+ int protocol_family)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::shared_open");
+ int error = 0;
+
+ if (local == ACE_Addr::sap_any
+ && protocol_family == PF_INET)
+ {
+ if (ACE::bind_port (this->get_handle ()) == -1)
+ error = 1;
+ }
+ else if (ACE_OS::bind (this->get_handle (),
+ ACE_reinterpret_cast (sockaddr *,
+ local.get_addr ()),
+ local.get_size ()) == -1)
+ error = 1;
+
+ if (error != 0)
+ this->close ();
+
+ return error ? -1 : 0;
+}
+
+int
+ACE_SOCK_Dgram::open (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ if (ACE_SOCK::open (SOCK_DGRAM,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ return -1;
+ else if (this->shared_open (local,
+ protocol_family) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+// Here's the general-purpose open routine.
+
+int
+ACE_SOCK_Dgram::open (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::open");
+
+ if (local != ACE_Addr::sap_any)
+ protocol_family = local.get_type ();
+ else if (protocol_family == PF_UNSPEC)
+ {
+#if defined (ACE_HAS_IPV6)
+ protocol_family = ACE_Sock_Connect::ipv6_enabled () ? PF_INET6 : PF_INET;
+#else
+ protocol_family = PF_INET;
+#endif /* ACE_HAS_IPV6 */
+ }
+
+ if (ACE_SOCK::open (SOCK_DGRAM,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+ else
+ return this->shared_open (local,
+ protocol_family);
+}
+
+// Here's the general-purpose constructor used by a connectionless
+// datagram ``server''...
+
+ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
+
+ if (this->open (local,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
+}
+
+ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g,
+ u_long flags,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
+ if (this->open (local,
+ protocol_family,
+ protocol,
+ protocolinfo,
+ g,
+ flags,
+ reuse_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
+}
+
+#if defined (ACE_HAS_MSG)
+// Send an iovec of size N to ADDR as a datagram (connectionless
+// version).
+
+ssize_t
+ACE_SOCK_Dgram::send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+ msghdr send_msg;
+
+ send_msg.msg_iov = (iovec *) iov;
+ send_msg.msg_iovlen = n;
+#if defined (ACE_HAS_SOCKADDR_MSG_NAME)
+ send_msg.msg_name = (struct sockaddr *) addr.get_addr ();
+#else
+ send_msg.msg_name = (char *) addr.get_addr ();
+#endif /* ACE_HAS_SOCKADDR_MSG_NAME */
+ send_msg.msg_namelen = addr.get_size ();
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ send_msg.msg_control = 0;
+ send_msg.msg_controllen = 0;
+ send_msg.msg_flags = 0;
+#else
+ send_msg.msg_accrights = 0;
+ send_msg.msg_accrightslen = 0;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ return ACE_OS::sendmsg (this->get_handle (),
+ &send_msg,
+ flags);
+}
+
+// Recv an iovec of size N to ADDR as a datagram (connectionless
+// version).
+
+ssize_t
+ACE_SOCK_Dgram::recv (iovec iov[],
+ size_t n,
+ ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+ msghdr recv_msg;
+
+ recv_msg.msg_iov = (iovec *) iov;
+ recv_msg.msg_iovlen = n;
+#if defined (ACE_HAS_SOCKADDR_MSG_NAME)
+ recv_msg.msg_name = (struct sockaddr *) addr.get_addr ();
+#else
+ recv_msg.msg_name = (char *) addr.get_addr ();
+#endif /* ACE_HAS_SOCKADDR_MSG_NAME */
+ recv_msg.msg_namelen = addr.get_size ();
+
+#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
+ recv_msg.msg_control = 0 ;
+ recv_msg.msg_controllen = 0 ;
+#else
+ recv_msg.msg_accrights = 0;
+ recv_msg.msg_accrightslen = 0;
+#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
+
+ ssize_t status = ACE_OS::recvmsg (this->get_handle (),
+ &recv_msg,
+ flags);
+ addr.set_size (recv_msg.msg_namelen);
+ return status;
+}
+
+#else /* ACE_HAS_MSG */
+
+// Send an iovec of size N to ADDR as a datagram (connectionless
+// version).
+
+ssize_t
+ACE_SOCK_Dgram::send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+
+ size_t length = 0;
+ size_t i;
+
+ // Determine the total length of all the buffers in <iov>.
+ for (i = 0; i < n; i++)
+#if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
+ // The iov_len is unsigned in Borland. If we go ahead and try the
+ // if, it will emit a warning.
+ if (iov[i].iov_len < 0)
+ return -1;
+ else
+#endif
+ length += iov[i].iov_len;
+
+ char *buf;
+
+#if defined (ACE_HAS_ALLOCA)
+ buf = alloca (length);
+#else
+ ACE_NEW_RETURN (buf,
+ char[length],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ char *ptr = buf;
+
+ for (i = 0; i < n; i++)
+ {
+ ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len);
+ ptr += iov[i].iov_len;
+ }
+
+ ssize_t result = ACE_SOCK_Dgram::send (buf, length, addr, flags);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] buf;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ return result;
+}
+
+// Recv an iovec of size N to ADDR as a datagram (connectionless
+// version).
+
+ssize_t
+ACE_SOCK_Dgram::recv (iovec iov[],
+ size_t n,
+ ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+
+ ssize_t length = 0;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+#if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
+ // The iov_len is unsigned in Borland. If we go ahead and try the
+ // if, it will emit a warning.
+ if (iov[i].iov_len < 0)
+ return -1;
+ else
+#endif
+ length += iov[i].iov_len;
+
+ char *buf;
+
+#if defined (ACE_HAS_ALLOCA)
+ buf = alloca (length);
+#else
+ ACE_NEW_RETURN (buf,
+ char[length],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ length = ACE_SOCK_Dgram::recv (buf, length, addr, flags);
+
+ if (length != -1)
+ {
+ char *ptr = buf;
+ int copyn = length;
+
+ for (i = 0;
+ i < n && copyn > 0;
+ i++)
+ {
+ ACE_OS::memcpy (iov[i].iov_base, ptr,
+ // iov_len is int on some platforms, size_t on others
+ copyn > (int) iov[i].iov_len
+ ? (size_t) iov[i].iov_len
+ : (size_t) copyn);
+ ptr += iov[i].iov_len;
+ copyn -= iov[i].iov_len;
+ }
+ }
+
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] buf;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ return length;
+}
+
+#endif /* ACE_HAS_MSG */
+
+ssize_t
+ACE_SOCK_Dgram::recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_Handle_Set handle_set;
+ handle_set.reset ();
+ handle_set.set_bit (this->get_handle ());
+
+ // Check the status of the current socket.
+ switch (ACE_OS::select (int (this->get_handle ()) + 1,
+ handle_set,
+ 0,
+ 0,
+ timeout))
+ {
+ case -1:
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ errno = ETIME;
+ return -1;
+ /* NOTREACHED */
+ default:
+ // Goes fine, call <recv> to get data
+ return this->recv (buf, n, addr, flags);
+ }
+}
+
+ssize_t
+ACE_SOCK_Dgram::send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_Handle_Set handle_set;
+ handle_set.reset ();
+ handle_set.set_bit (this->get_handle ());
+
+ // Check the status of the current socket.
+ switch (ACE_OS::select (int (this->get_handle ()) + 1,
+ 0,
+ handle_set,
+ 0,
+ timeout))
+ {
+ case -1:
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ errno = ETIME;
+ return -1;
+ /* NOTREACHED */
+ default:
+ // Goes fine, call <send> to transmit the data.
+ return this->send (buf, n, addr, flags);
+ }
+}
+
+void
+ACE_SOCK_Dgram::set_nic (const char *option_value)
+{
+ /* The first step would be to get the interface address for the
+ nic_name specified */
+ ip_mreq multicast_address;
+ ACE_INET_Addr mcast_addr;
+#if defined (ACE_WIN32)
+ // This port number is not necessary, just convenient
+ ACE_INET_Addr interface_addr;
+ if (interface_addr.set (mcast_addr.get_port_number (),
+ option_value) == -1)
+ return;
+ multicast_address.imr_interface.s_addr =
+ htonl (interface_addr.get_ip_address ());
+#else
+ ifreq if_address;
+
+#if defined (ACE_PSOS)
+ // Look up the interface by number, not name.
+ if_address.ifr_ifno = ACE_OS::atoi (option_value);
+#else
+ ACE_OS::strcpy (if_address.ifr_name, option_value);
+#endif /* defined (ACE_PSOS) */
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ SIOCGIFADDR,
+ &if_address) == -1)
+ return;
+
+ /* Cast this into the required format */
+ sockaddr_in *socket_address;
+ socket_address = ACE_reinterpret_cast(sockaddr_in *,
+ &if_address.ifr_addr);
+ multicast_address.imr_interface.s_addr = socket_address->sin_addr.s_addr;
+
+ /*
+ * Now. I got the interface address for the 'nic' specified.
+ * Use that to set the nic option.
+ */
+
+ this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_MULTICAST_IF,
+ &multicast_address.imr_interface.s_addr,
+ sizeof (struct in_addr));
+#endif /* ACE_WIN32 */
+
+}
diff --git a/ace/Sockets/SOCK_Dgram.h b/ace/Sockets/SOCK_Dgram.h
new file mode 100644
index 00000000000..e227f9387af
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram.h
@@ -0,0 +1,214 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SOCK_DGRAM_H
+#define ACE_SOCK_DGRAM_H
+#include "ace/pre.h"
+
+#include "ace/SOCK.h"
+#include "ace/INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Addr.h"
+
+/**
+ * @class ACE_SOCK_Dgram
+ *
+ * @brief Defines the member functions for the ACE_SOCK datagram
+ * abstraction.
+ */
+class ACE_Export ACE_SOCK_Dgram : public ACE_SOCK
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Dgram (void);
+
+ /// This is a BSD-style method (i.e., no QoS) for initiating a socket
+ /// dgram that will accept datagrams at the <local> address.
+ ACE_SOCK_Dgram (const ACE_Addr &local,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /**
+ * This is a QoS-enabed method for initiating a socket dgram that
+ * will accept datagrams at the <local> address. The <qos_params>
+ * are passed to <ACE_OS::join_leaf>.
+ */
+ ACE_SOCK_Dgram (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ int reuse_addr = 0);
+
+ /// This is a BSD-style method (i.e., no QoS) for initiating a socket
+ /// dgram that will accept datagrams at the <local> address.
+ int open (const ACE_Addr &local,
+ int protocol_family = ACE_PROTOCOL_FAMILY_INET,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /**
+ * This is a QoS-enabed method for initiating a socket dgram that
+ * will accept datagrams at the <local> address. The <qos_params>
+ * are passed to <ACE_OS::join_leaf>.
+ */
+ int open (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ ACE_Protocol_Info *protocolinfo,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ int reuse_addr = 0);
+
+ /// Default dtor.
+ ~ACE_SOCK_Dgram (void);
+
+ // = Data transfer routines.
+ /// Send an <n> byte <buf> to the datagram socket (uses <sendto(3)>).
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /// Receive an <n> byte <buf> from the datagram socket (uses
+ /// <recvfrom(3)>).
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags = 0) const;
+
+ /**
+ * Allows a client to read from a socket without having to provide a
+ * buffer to read. This method determines how much data is in the
+ * socket, allocates a buffer of this size, reads in the data, and
+ * returns the number of bytes read. The caller is responsible for
+ * deleting the member in the <iov_base> field of <io_vec> using the
+ * ``delete []'' syntax.
+ */
+ ssize_t recv (iovec *io_vec,
+ ACE_Addr &addr,
+ int flags = 0,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send an <iovec> of size <n> to the datagram socket (uses
+ /// <sendmsg(3)>).
+ ssize_t send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /// Recv an <iovec> of size <n> to the datagram socket (uses
+ /// <recvmsg(3)>).
+ ssize_t recv (iovec iov[],
+ size_t n,
+ ACE_Addr &addr,
+ int flags = 0) const;
+
+ /**
+ * Wait up to <timeout> amount of time to receive a datagram into
+ * <buf>. The <ACE_Time_Value> indicates how long to blocking
+ * trying to receive. If <timeout> == 0, the caller will block
+ * until action is possible, else will wait until the relative time
+ * specified in *<timeout> elapses). If <recv> times out a -1 is
+ * returned with <errno == ETIME>. If it succeeds the number of
+ * bytes received is returned.
+ */
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags,
+ const ACE_Time_Value *timeout) const;
+
+ /**
+ * Wait up to <timeout> amount of time to receive a datagram into
+ * <buf>. The <ACE_Time_Value> indicates how long to blocking
+ * trying to receive. If <timeout> == 0, the caller will block
+ * until action is possible, else will wait until the relative time
+ * specified in *<timeout> elapses). If <send> times out a -1 is
+ * returned with <errno == ETIME>. If it succeeds the number of
+ * bytes sent is returned.
+ */
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags,
+ const ACE_Time_Value *timeout) const;
+
+ /// Send <buffer_count> worth of <buffers> to <addr> using overlapped
+ /// I/O (uses <WSASentTo>). Returns 0 on success.
+ ssize_t send (const iovec buffers[],
+ int buffer_count,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const;
+
+ /// Recv <buffer_count> worth of <buffers> from <addr> using
+ /// overlapped I/O (uses <WSARecvFrom>). Returns 0 on success.
+ ssize_t recv (iovec buffers[],
+ int buffer_count,
+ size_t &number_of_bytes_recvd,
+ int &flags,
+ ACE_Addr &addr,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const;
+
+ /// Send an <n> byte <buf> to the datagram socket (uses <WSASentTo>).
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const;
+
+ /// Receive an <n> byte <buf> from the datagram socket (uses
+ /// <WSARecvFrom>).
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ void set_nic (const char *option_value);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Open is shared by this and by <LSOCK_Dgram>.
+ int shared_open (const ACE_Addr &local,
+ int protocol_family);
+
+private:
+ /// Do not allow this function to percolate up to this interface...
+ int get_remote_addr (ACE_Addr &) const;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_H */
diff --git a/ace/Sockets/SOCK_Dgram.i b/ace/Sockets/SOCK_Dgram.i
new file mode 100644
index 00000000000..8a7c094f8a5
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram.i
@@ -0,0 +1,158 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_Dgram.i
+
+// Here's the simple-minded constructor.
+
+ASYS_INLINE
+ACE_SOCK_Dgram::ACE_SOCK_Dgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
+}
+
+ASYS_INLINE
+ACE_SOCK_Dgram::~ACE_SOCK_Dgram (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::~ACE_SOCK_Dgram");
+}
+
+// <sendto> an N byte datagram to <addr> (connectionless version).
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ size_t len = addr.get_size ();
+ return ACE_OS::sendto (this->get_handle (),
+ (const char *) buf,
+ n,
+ flags,
+ (struct sockaddr *) saddr,
+ len);
+}
+
+// <recvfrom> an n byte datagram (connectionless version).
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ int addr_len = addr.get_size ();
+
+ ssize_t status = ACE_OS::recvfrom (this->get_handle (),
+ (char *) buf,
+ n,
+ flags,
+ (sockaddr *) saddr,
+ &addr_len);
+ addr.set_size (addr_len);
+ return status;
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::send (const iovec buffers[],
+ int buffer_count,
+ size_t &number_of_bytes_sent,
+ int flags,
+ const ACE_Addr &addr,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ size_t len = addr.get_size ();
+ return ACE_OS::sendto (this->get_handle (),
+ buffers,
+ buffer_count,
+ number_of_bytes_sent,
+ flags,
+ (const sockaddr *) saddr,
+ len,
+ overlapped,
+ func);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::recv (iovec buffers[],
+ int buffer_count,
+ size_t &number_of_bytes_recvd,
+ int &flags,
+ ACE_Addr &addr,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ int addr_len = addr.get_size ();
+
+ ssize_t status = ACE_OS::recvfrom (this->get_handle (),
+ buffers,
+ buffer_count,
+ number_of_bytes_recvd,
+ flags,
+ (sockaddr *) saddr,
+ &addr_len,
+ overlapped,
+ func);
+ addr.set_size (addr_len);
+ return status;
+}
+
+// <sendto> an N byte datagram to <addr> (connectionless version).
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::send");
+
+ iovec buffer[1];
+ buffer[0].iov_len = n;
+ buffer[0].iov_base = (char *) buf;
+ size_t number_of_bytes_sent = 0;
+ return this->send (buffer,
+ 1,
+ number_of_bytes_sent,
+ flags,
+ addr,
+ overlapped,
+ func);
+}
+
+// <recvfrom> an n byte datagram (connectionless version).
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram::recv (void *buf,
+ size_t n,
+ ACE_Addr &addr,
+ int flags,
+ ACE_OVERLAPPED *overlapped,
+ ACE_OVERLAPPED_COMPLETION_FUNC func) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram::recv");
+
+ iovec buffer[1];
+ buffer[0].iov_len = n;
+ buffer[0].iov_base = (char *) buf;
+ size_t number_of_bytes_recvd = 0;
+ return this->recv (buffer,
+ 1,
+ number_of_bytes_recvd,
+ flags,
+ addr,
+ overlapped,
+ func);
+}
diff --git a/ace/Sockets/SOCK_Dgram_Bcast.cpp b/ace/Sockets/SOCK_Dgram_Bcast.cpp
new file mode 100644
index 00000000000..e819e798555
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Bcast.cpp
@@ -0,0 +1,333 @@
+// $Id$
+
+#include "ace/SOCK_Dgram_Bcast.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram_Bcast.i"
+#endif
+
+ACE_RCSID(ace, SOCK_Dgram_Bcast, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast)
+
+ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr &addr,
+ ACE_Bcast_Node *next)
+ : bcast_addr_ (addr),
+ next_ (next)
+{
+ ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
+}
+
+void
+ACE_SOCK_Dgram_Bcast::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
+}
+
+// Close up and release resources.
+
+int
+ACE_SOCK_Dgram_Bcast::close (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
+
+ ACE_Bcast_Node *temp = this->if_list_;
+
+ // Release the dynamically allocated memory.
+
+ while (temp != 0)
+ {
+ ACE_Bcast_Node *hold = temp->next_;
+ delete temp;
+ temp = hold;
+ }
+
+ // Shut down the descriptor.
+ return ACE_SOCK::close ();
+}
+
+// Here's the simple-minded constructor.
+
+ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (void)
+ : if_list_ (0)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
+}
+
+// Here's the general-purpose constructor used by a connectionless
+// datagram ``server''...
+
+ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ int reuse_addr,
+ const ACE_TCHAR *host_name)
+ : ACE_SOCK_Dgram (local, protocol_family, protocol, reuse_addr),
+ if_list_ (0)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
+
+ if (this->mk_broadcast (host_name) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_SOCK_Dgram_Bcast")));
+}
+
+// Here's the general-purpose open routine.
+
+int
+ACE_SOCK_Dgram_Bcast::open (const ACE_Addr &local,
+ int protocol_family,
+ int protocol,
+ int reuse_addr,
+ const ACE_TCHAR *host_name)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open");
+
+ if (this->ACE_SOCK_Dgram::open (local, protocol_family,
+ protocol, reuse_addr) == -1)
+ return -1;
+
+ return this->mk_broadcast (host_name);
+}
+
+// Make broadcast available for Datagram socket.
+
+int
+ACE_SOCK_Dgram_Bcast::mk_broadcast (const ACE_TCHAR *host_name)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast");
+
+ int one = 1;
+
+ if (ACE_OS::setsockopt (this->get_handle (),
+ SOL_SOCKET,
+ SO_BROADCAST,
+ (char *) &one,
+ sizeof one) == -1)
+ return -1;
+
+#if !defined (ACE_WIN32)
+ ACE_HANDLE s = this->get_handle ();
+
+ char buf[BUFSIZ];
+ struct ifconf ifc;
+
+ ifc.ifc_len = sizeof buf;
+ ifc.ifc_buf = buf;
+
+ // Get interface structure and initialize the addresses using UNIX
+ // techniques.
+ if (ACE_OS::ioctl (s,
+ SIOCGIFCONF,
+ (char *) &ifc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)"),
+ ACE_INVALID_HANDLE);
+
+ struct ifreq *ifr = ifc.ifc_req;
+
+ struct sockaddr_in host_addr;
+
+ //Get host ip address
+ if (host_name)
+ {
+ hostent *hp = ACE_OS::gethostbyname (host_name);
+
+ if (hp == 0)
+ return -1;
+ else
+#if defined(_UNICOS)
+ {
+ ACE_UINT64 haddr; // a place to put the address
+ char * haddrp = (char *) &haddr; // convert to char pointer
+ ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
+ host_addr.sin_addr.s_addr = haddr;
+ }
+#else /* ! _UNICOS */
+ ACE_OS::memcpy ((char *) &host_addr.sin_addr.s_addr,
+ (char *) hp->h_addr,
+ hp->h_length);
+#endif /* ! _UNICOS */
+ }
+
+ for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
+#if !defined(CHORUS_4) && !defined(AIX)
+ n--, ifr++)
+#else
+ n--,
+ ((ifr->ifr_addr.sa_len <= sizeof (struct sockaddr)) ?
+ ifr++ :
+ ifr = (struct ifreq *)
+ (ifr->ifr_addr.sa_len + (caddr_t) &ifr->ifr_addr)))
+#endif /* CHORUS_4 */
+ {
+ // Compare host ip address with interface ip address.
+ if (host_name)
+ {
+ struct sockaddr_in if_addr;
+
+ ACE_OS::memcpy (&if_addr,
+ &ifr->ifr_addr,
+ sizeof if_addr);
+
+ if (host_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
+ continue;
+ }
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ {
+ // Note that some systems seem to generate 0 (AF_UNDEF) for
+ // the sa_family, even when there are no errors! Thus, we
+ // only print an error if this is not the case, or if we're
+ // in "debugging" mode.
+ if (ifr->ifr_addr.sa_family != 0
+ || ACE::debug () > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "warning %p: sa_family: %d\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET",
+ ifr->ifr_addr.sa_family));
+ continue;
+ }
+
+ struct ifreq flags = *ifr;
+ struct ifreq if_req = *ifr;
+
+ if (ACE_OS::ioctl (s,
+ SIOCGIFFLAGS,
+ (char *) &flags) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)"));
+ continue;
+ }
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags,
+ IFF_UP) == 0)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up"));
+ continue;
+ }
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags,
+ IFF_LOOPBACK))
+ continue;
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags,
+ IFF_BROADCAST))
+ {
+ if (ACE_OS::ioctl (s,
+ SIOCGIFBRDADDR,
+ (char *) &if_req) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)"));
+ else
+ {
+ ACE_INET_Addr addr (ACE_reinterpret_cast (sockaddr_in *,
+ &if_req.ifr_broadaddr),
+ sizeof if_req.ifr_broadaddr);
+ ACE_NEW_RETURN (this->if_list_,
+ ACE_Bcast_Node (addr,
+ this->if_list_),
+ -1);
+ }
+ }
+ else
+ ACE_ERROR ((LM_ERROR, "%p\n",
+ "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface."));
+ }
+#else
+ ACE_UNUSED_ARG (host_name);
+
+ ACE_INET_Addr addr (u_short (0),
+ ACE_UINT32 (INADDR_BROADCAST));
+ ACE_NEW_RETURN (this->if_list_,
+ ACE_Bcast_Node (addr,
+ this->if_list_),
+ -1);
+#endif /* !ACE_WIN32 */
+ return this->if_list_ == 0 ? -1 : 0;
+}
+
+// Broadcast the datagram to every interface. Returns the average
+// number of bytes sent.
+
+ssize_t
+ACE_SOCK_Dgram_Bcast::send (const void *buf,
+ size_t n,
+ u_short port_number,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
+ size_t iterations = 0;
+ ssize_t total_bytes = 0;
+
+ if (this->if_list_ == 0)
+ return -1;
+
+ for (ACE_Bcast_Node *temp = this->if_list_;
+ temp != 0;
+ temp = temp->next_)
+ {
+ temp->bcast_addr_.set_port_number (port_number);
+
+ ssize_t bytes_sent = ACE_SOCK_Dgram::send (buf,
+ n,
+ temp->bcast_addr_,
+ flags);
+
+ if (bytes_sent == -1)
+ return -1;
+ else
+ total_bytes += bytes_sent;
+
+ iterations++;
+ }
+
+ return iterations == 0 ? 0 : total_bytes / iterations;
+}
+
+#if defined (ACE_HAS_MSG)
+// Broadcast datagram to every interfaces.
+
+ssize_t
+ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
+ size_t n,
+ u_short /* port_number */,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
+
+ if (this->if_list_ == 0)
+ return -1;
+
+ // Send the message to every interface.
+
+ for (ACE_Bcast_Node *temp = this->if_list_;
+ temp != 0;
+ temp++)
+ if (ACE_SOCK_Dgram::send (iov,
+ n,
+ temp->bcast_addr_,
+ flags) == -1)
+ return -1;
+
+ return 0;
+}
+
+// Broadcast an iovec of size N to ADDR as a datagram (note that addr
+// must be preassigned to the broadcast address of the subnet...).
+
+ssize_t
+ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
+
+ return ACE_SOCK_Dgram::send (iov, n, addr, flags);
+}
+#endif /* ACE_HAS_MSG */
diff --git a/ace/Sockets/SOCK_Dgram_Bcast.h b/ace/Sockets/SOCK_Dgram_Bcast.h
new file mode 100644
index 00000000000..e16c0d2296b
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Bcast.h
@@ -0,0 +1,133 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram_Bcast.h
+ *
+ * $Id$
+ *
+ * @author Doug Schmidt
+ */
+//=============================================================================
+
+
+#ifndef ACE_SOCK_DGRAM_BCAST_H
+#define ACE_SOCK_DGRAM_BCAST_H
+#include "ace/pre.h"
+
+#include "ace/INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Dgram.h"
+
+/**
+ * @class ACE_Bcast_Node
+ *
+ * @brief Linked list of broadcast interfaces.
+ */
+class ACE_Export ACE_Bcast_Node
+{
+public:
+ /// Default dtor.
+ ACE_Bcast_Node (ACE_INET_Addr &,
+ ACE_Bcast_Node *);
+ ~ACE_Bcast_Node (void);
+
+ /// Broadcast address for the interface.
+ ACE_INET_Addr bcast_addr_;
+
+ /// Pointer to the next interface in the chain.
+ ACE_Bcast_Node *next_;
+};
+
+/**
+ * @class ACE_SOCK_Dgram_Bcast
+ *
+ * @brief Defines the member functions for the ACE_SOCK datagram
+ * abstraction.
+ */
+class ACE_Export ACE_SOCK_Dgram_Bcast : public ACE_SOCK_Dgram
+{
+public:
+ // = Initialization and termination methods.
+ /// Default constructor.
+ ACE_SOCK_Dgram_Bcast (void);
+
+ ACE_SOCK_Dgram_Bcast (const ACE_Addr &local,
+ int protocol_family = PF_INET,
+ int protocol = 0,
+ int reuse_addr = 0,
+ const ACE_TCHAR *host_name = 0);
+
+ /// Default dtor.
+ ~ACE_SOCK_Dgram_Bcast (void);
+
+ // Initiate a connectionless datagram broadcast endpoint.
+
+ /// Initiate a connectionless datagram broadcast endpoint.
+ int open (const ACE_Addr &local,
+ int protocol_family = PF_INET,
+ int protocol = 0,
+ int reuse_addr = 0,
+ const ACE_TCHAR *host_name = 0);
+
+ /// Close up and release dynamically allocated resources.
+ int close (void);
+
+ /// Broadcast the datagram to every interface. Returns the average
+ /// number of bytes sent.
+ ssize_t send (const void *buf,
+ size_t n,
+ u_short portnum,
+ int flags = 0) const;
+
+ /// Broadcast the <iovec> datagrams to every interface. Returns the
+ /// average number of bytes sent.
+ ssize_t send (const iovec iov[],
+ size_t n,
+ u_short portnum,
+ int flags = 0) const;
+
+ /// Broadcast an N byte datagram to ADDR (note that addr must be
+ /// preassigned to the broadcast address of the subnet...).
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /**
+ * Broadcast an <iovec> of size <n> to <addr> as a datagram (note
+ * that addr must be preassigned to the broadcast address of the
+ * subnet...)
+ */
+ ssize_t send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Make broadcast available for Datagram socket.
+ int mk_broadcast (const ACE_TCHAR *host_name);
+
+ /// Points to the head of the list of broadcast interfaces.
+ ACE_Bcast_Node *if_list_;
+
+ /// Do not allow this function to percolate up to this interface...
+ int get_remote_addr (ACE_Addr &) const;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram_Bcast.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_BCAST_H */
diff --git a/ace/Sockets/SOCK_Dgram_Bcast.i b/ace/Sockets/SOCK_Dgram_Bcast.i
new file mode 100644
index 00000000000..9304ba1d933
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Bcast.i
@@ -0,0 +1,34 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_Dgram_Bcast.i
+
+ASYS_INLINE
+ACE_Bcast_Node::~ACE_Bcast_Node (void)
+{
+}
+
+ASYS_INLINE
+ACE_SOCK_Dgram_Bcast::~ACE_SOCK_Dgram_Bcast (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::~ACE_SOCK_Dgram_Bcast");
+}
+
+// Broadcast an N byte datagram to ADDR (note that addr must be
+// preassigned to the broadcast address of the subnet...)
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram_Bcast::send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
+
+ sockaddr *saddr = (sockaddr *) addr.get_addr ();
+ size_t len = addr.get_size ();
+ return ACE_OS::sendto (this->get_handle (), (const char *) buf, n, flags,
+ (struct sockaddr *) saddr, len);
+}
+
+
diff --git a/ace/Sockets/SOCK_Dgram_Mcast.cpp b/ace/Sockets/SOCK_Dgram_Mcast.cpp
new file mode 100644
index 00000000000..2ca7530b51b
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Mcast.cpp
@@ -0,0 +1,414 @@
+// $Id$
+
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/INET_Addr.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram_Mcast.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+// This is a workaround for platforms with non-standard
+// definitions of the ip_mreq structure
+#if ! defined (IMR_MULTIADDR)
+#define IMR_MULTIADDR imr_multiaddr
+#endif /* ! defined (IMR_MULTIADDR) */
+
+ACE_RCSID(ace, SOCK_Dgram_Mcast, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Mcast)
+
+void
+ACE_SOCK_Dgram_Mcast::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump");
+}
+
+// Dummy default constructor...
+
+ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast");
+}
+
+int
+ACE_SOCK_Dgram_Mcast::open (const ACE_Addr &mcast_addr,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::open");
+
+ // Make a copy of address to use in the <send> methods. Note: Sun
+ // C++ 4.2 needs the useless const_cast.
+ this->mcast_addr_.set (ACE_reinterpret_cast (const ACE_INET_Addr &,
+ ACE_const_cast (ACE_Addr &,
+ mcast_addr)));
+ // Only perform the <open> initialization if we haven't been opened
+ // earlier.
+ if (this->get_handle () == ACE_INVALID_HANDLE)
+ {
+ if (ACE_SOCK::open (SOCK_DGRAM,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+
+ int one = 1;
+ if (reuse_addr
+ && this->ACE_SOCK::set_option (SOL_SOCKET,
+ SO_REUSEADDR,
+ &one,
+ sizeof one) == -1)
+ return -1;
+#if defined (SO_REUSEPORT)
+ else if (this->ACE_SOCK::set_option (SOL_SOCKET,
+ SO_REUSEPORT,
+ &one,
+ sizeof one) == -1)
+ return -1;
+#endif /* SO_REUSEPORT */
+
+ // Create an address to bind the socket to.
+ ACE_INET_Addr local;
+
+#if defined (linux)
+ local = this->mcast_addr_;
+#else /* linux */
+ if (local.set (this->mcast_addr_.get_port_number ()) == -1)
+ return -1;
+#endif /* linux */
+
+ if (ACE_SOCK_Dgram::shared_open (local,
+ protocol_family) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol,
+ int reuse_addr)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe_ifs");
+#if defined (ACE_WIN32)
+ // Windows NT's winsock has trouble with multicast subscribes in the
+ // presence of multiple network interfaces when the IP address is
+ // given as INADDR_ANY. It will pick the first interface and only
+ // accept mcast there. So, to work around this, cycle through all
+ // of the interfaces known and subscribe to all the non-loopback
+ // ones.
+ //
+ // Note that this only needs to be done on NT, but there's no way to
+ // tell at this point if the code will be running on NT - only if it
+ // is compiled for NT-only or for NT/95, and that doesn't really
+ // help us. It doesn't hurt to do this on Win95, it's just a little
+ // slower than it normally would be.
+ //
+ // NOTE - <ACE::get_ip_interfaces> doesn't always get all of the
+ // interfaces. In particular, it may not get a PPP interface. This
+ // is a limitation of the way <ACE::get_ip_interfaces> works with
+ // MSVC. The reliable way of getting the interface list is
+ // available only with MSVC 5.
+
+ if (net_if == 0)
+ {
+ ACE_INET_Addr *if_addrs = 0;
+ size_t if_cnt;
+
+ if (ACE::get_ip_interfaces (if_cnt,
+ if_addrs) != 0)
+ return -1;
+
+ size_t nr_subscribed = 0;
+
+ if (if_cnt < 2)
+ {
+ if (this->subscribe (mcast_addr,
+ reuse_addr,
+ ACE_LIB_TEXT ("0.0.0.0"),
+ protocol_family,
+ protocol) == 0)
+ ++nr_subscribed;
+ }
+ else
+ // Iterate through all the interfaces, figure out which ones
+ // offer multicast service, and subscribe to them.
+ while (if_cnt > 0)
+ {
+ --if_cnt;
+
+ // Convert to 0-based for indexing, next loop check.
+ if (if_addrs[if_cnt].get_ip_address() == INADDR_LOOPBACK)
+ continue;
+ if (this->subscribe (mcast_addr,
+ reuse_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr()),
+ protocol_family,
+ protocol) == 0)
+ ++nr_subscribed;
+ }
+
+ delete [] if_addrs;
+
+ if (nr_subscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+ else
+ // 1 indicates a "short-circuit" return. This handles the
+ // rather bizarre semantics of checking all the interfaces on
+ // NT.
+ return 1;
+ }
+#else
+ ACE_UNUSED_ARG (mcast_addr);
+ ACE_UNUSED_ARG (net_if);
+ ACE_UNUSED_ARG (protocol_family);
+ ACE_UNUSED_ARG (protocol);
+ ACE_UNUSED_ARG (reuse_addr);
+#endif /* ACE_WIN32 */
+ // Otherwise, do it like everyone else...
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::subscribe (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe");
+
+ if (this->open (mcast_addr,
+ protocol_family,
+ protocol,
+ reuse_addr) == -1)
+ return -1;
+
+ int result = this->subscribe_ifs (mcast_addr,
+ net_if,
+ protocol_family,
+ protocol,
+ reuse_addr);
+ // Check for the "short-circuit" return value of 1 (for NT). This
+ // handles the rather bizarre semantics of checking all the
+ // interfaces on NT.
+ if (result != 0)
+ return result;
+
+ ip_mreq multicast_address;
+
+ // Create multicast request.
+ result = this->make_multicast_address_i (mcast_addr,
+ multicast_address,
+ net_if);
+ if (result != 0)
+ return result;
+
+ // Tell network device driver to read datagrams with a
+ // multicast_address IP interface.
+ result = this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ &multicast_address,
+ sizeof multicast_address);
+ if (result != 0)
+ return result;
+
+ // Set the <mcast_request_if_> field. This is mostly a convenience
+ // for applications that subscribe to a single multicast group,
+ // using the internal field allows them to simply call the
+ // unsubscribe() operation.
+ // Notice that such applications are using a non-reentrant interface
+ // of the class, and thus should use proper synchronization for it.
+ this->mcast_request_if_ = multicast_address;
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe_ifs");
+#if defined (ACE_WIN32)
+ // Windows NT's winsock has trouble with multicast subscribes in the
+ // presence of multiple network interfaces when the IP address is
+ // given as INADDR_ANY. It will pick the first interface and only
+ // accept mcast there. So, to work around this, cycle through all
+ // of the interfaces known and subscribe to all the non-loopback
+ // ones.
+ //
+ // Note that this only needs to be done on NT, but there's no way to
+ // tell at this point if the code will be running on NT - only if it
+ // is compiled for NT-only or for NT/95, and that doesn't really
+ // help us. It doesn't hurt to do this on Win95, it's just a little
+ // slower than it normally would be.
+ //
+ // NOTE - <ACE::get_ip_interfaces> doesn't always get all of the
+ // interfaces. In particular, it may not get a PPP interface. This
+ // is a limitation of the way <ACE::get_ip_interfaces> works with
+ // MSVC. The reliable way of getting the interface list is
+ // available only with MSVC 5.
+
+ if (net_if == 0)
+ {
+ ACE_INET_Addr *if_addrs = 0;
+ size_t if_cnt;
+
+ if (ACE::get_ip_interfaces (if_cnt,
+ if_addrs) != 0)
+ return -1;
+
+ size_t nr_unsubscribed = 0;
+
+ if (if_cnt < 2)
+ {
+ if (this->unsubscribe (mcast_addr,
+ ACE_LIB_TEXT ("0.0.0.0"),
+ protocol_family,
+ protocol) == 0)
+ ++nr_unsubscribed;
+ }
+ else
+ while (if_cnt > 0)
+ {
+ --if_cnt;
+ // Convert to 0-based for indexing, next loop check
+ if (if_addrs[if_cnt].get_ip_address() == INADDR_LOOPBACK)
+ continue;
+ if (this->unsubscribe (mcast_addr,
+ ACE_TEXT_CHAR_TO_TCHAR
+ (if_addrs[if_cnt].get_host_addr()),
+ protocol_family,
+ protocol) == 0)
+ ++nr_unsubscribed;
+ }
+
+ delete [] if_addrs;
+
+ if (nr_unsubscribed == 0)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return 1;
+ }
+#else
+ ACE_UNUSED_ARG (mcast_addr);
+ ACE_UNUSED_ARG (net_if);
+ ACE_UNUSED_ARG (protocol_family);
+ ACE_UNUSED_ARG (protocol);
+#endif /* ACE_WIN32 */
+
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::unsubscribe (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
+ int result = this->unsubscribe_ifs (mcast_addr,
+ net_if,
+ protocol_family,
+ protocol);
+
+ // Check for the "short-circuit" return value of 1 (for NT).
+ if (result != 0)
+ return result;
+
+ // Otherwise, do it like everyone else.
+
+ ip_mreq multicast_address;
+
+ // Create multicast request.
+ result = this->make_multicast_address_i (mcast_addr,
+ multicast_address,
+ net_if);
+ if (result != 0)
+ return result;
+
+ // Tell network device driver to stop reading datagrams with the
+ // <mcast_addr>.
+ return ACE_SOCK::set_option (IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &multicast_address,
+ sizeof multicast_address);
+}
+
+int
+ACE_SOCK_Dgram_Mcast::unsubscribe (void)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe");
+ return this->ACE_SOCK::set_option (IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &this->mcast_request_if_,
+ sizeof this->mcast_request_if_);
+}
+
+int
+ACE_SOCK_Dgram_Mcast::make_multicast_address_i (const ACE_INET_Addr &mcast_addr,
+ ip_mreq &multicast_address ,
+ const ACE_TCHAR *net_if)
+{
+ if (net_if != 0)
+ {
+#if defined (ACE_WIN32)
+ // This port number is not necessary, just convenient
+ ACE_INET_Addr interface_addr;
+ if (interface_addr.set (mcast_addr.get_port_number (),
+ net_if) == -1)
+ return -1;
+ multicast_address.imr_interface.s_addr =
+ htonl (interface_addr.get_ip_address ());
+#else
+ ifreq if_address;
+
+#if defined (ACE_PSOS)
+ // Look up the interface by number, not name.
+ if_address.ifr_ifno = ACE_OS::atoi (net_if);
+#else
+ ACE_OS::strcpy (if_address.ifr_name, net_if);
+#endif /* defined (ACE_PSOS) */
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ SIOCGIFADDR,
+ &if_address) == -1)
+ return -1;
+
+ sockaddr_in *socket_address;
+ socket_address = ACE_reinterpret_cast(sockaddr_in *,
+ &if_address.ifr_addr);
+ multicast_address.imr_interface.s_addr = socket_address->sin_addr.s_addr;
+#endif /* ACE_WIN32 */
+ }
+ else
+ multicast_address.imr_interface.s_addr = INADDR_ANY;
+
+ multicast_address.IMR_MULTIADDR.s_addr = htonl (mcast_addr.get_ip_address ());
+ return 0;
+}
+
+int
+ACE_SOCK_Dgram_Mcast::make_multicast_address (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_address");
+
+ return this->make_multicast_address_i (mcast_addr,
+ this->mcast_request_if_,
+ net_if );
+}
diff --git a/ace/Sockets/SOCK_Dgram_Mcast.h b/ace/Sockets/SOCK_Dgram_Mcast.h
new file mode 100644
index 00000000000..7d9269f0bd4
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Mcast.h
@@ -0,0 +1,193 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Dgram_Mcast.h
+ *
+ * $Id$
+ *
+ * @author Irfan Pyrali <irfan@cs.wustl.edu>
+ * @author Tim Harrison <harrison@cs.wustl.edu>
+ * @author and Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SOCK_DGRAM_MCAST_H
+#define ACE_SOCK_DGRAM_MCAST_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_Dgram.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+
+/**
+ * @class ACE_SOCK_Dgram_Mcast
+ *
+ * @brief Defines the member functions for the ACE socket wrapper
+ * for UDP/IP multicast.
+ */
+class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram
+{
+public:
+ // = Initialization routine.
+ /**
+ * Note that there is no public <open> method. Therefore, this
+ * class cannot be used unless you <subscribe> to a multicast group.
+ * If you just want to send (and not listen) to a multicast group,
+ * use <ACE_SOCK_Dgram> or <ACE_SOCK_CODgram> instead.
+ */
+ ACE_SOCK_Dgram_Mcast (void);
+
+ /// Default dtor.
+ ~ACE_SOCK_Dgram_Mcast (void);
+
+ // = Multicast group management routines.
+
+ /**
+ * This is a BSD-style method (i.e., no QoS) for joining a multicast
+ * group. The network interface device driver is instructed to
+ * accept datagrams with <mcast_addr> multicast addresses. If the
+ * socket has already been opened, <subscribe> closes the socket and
+ * opens a new socket bound to the <mcast_addr>.
+ *
+ * The <net_if> interface is hardware specific, e.g., use "netstat
+ * -i" to find whether your interface is, such as "le0" or something
+ * else. If net_if == 0, <subscribe> uses the default mcast
+ * interface. Returns: -1 if the call fails.
+ *
+ * Note that some platforms, such as pSoS, support only number, not
+ * names, for network interfaces. For these platforms, just give
+ * these numbers in alphanumeric form and <subscribe> will convert
+ * them into numbers via <ACE_OS::atoi>.
+ */
+ int subscribe (const ACE_INET_Addr &mcast_addr,
+ int reuse_addr = 1,
+ const ACE_TCHAR *net_if = 0,
+ int protocol_family = PF_INET,
+ int protocol = 0);
+
+ /**
+ * Leave a multicast group identified by <mcast_addr>. The <net_if>
+ * interface is hardware specific. Use something like "netstat -i"
+ * to find whether your interface is, such as "le0" or something
+ * else. If <net_if> == 0, <subscribe> uses the default mcast
+ * interface. Returns: -1 if the call fails.
+ *
+ * Note that some platforms, such as pSoS, support only number, not
+ * names, for network interfaces. For these platforms, just give
+ * these numbers in alphanumeric form and <subscribe> will convert
+ * them into numbers via <ACE_OS::atoi>.
+ */
+ int unsubscribe (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0,
+ int protocol_family = PF_INET,
+ int protocol = 0);
+
+ /// Unsubscribe from a multicast group. Returns -1 if the call
+ /// fails.
+ int unsubscribe (void);
+
+ // = Data transfer routines.
+ /// Send <n> bytes in <buf>.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags = 0) const;
+
+ /// Send <n> <iovecs>.
+ ssize_t send (const iovec iov[],
+ size_t n,
+ int flags = 0) const;
+
+ // = Options.
+ /**
+ * Set an ip option that takes a char as input, such as
+ * <IP_MULTICAST_LOOP> or <IP_MULTICAST_TTL>. This is just a more
+ * concise nice interface to a subset of possible
+ * <ACE_SOCK::set_option> calls. Returns 0 on success, -1 on
+ * failure.
+ */
+ int set_option (int option,
+ char optval);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ // = Disable public <open> method to ensure class used properly.
+
+ /// Not publically visible.
+ int open (const ACE_Addr &mcast_addr,
+ int protocol_family = PF_INET,
+ int protocol = 0,
+ int reuse_addr = 0);
+
+ /// Not publically visible.
+ int open (const ACE_Addr &mcast_addr,
+ const ACE_QoS_Params &qos_params,
+ int protocol_family = PF_INET,
+ int protocol = 0,
+ ACE_Protocol_Info *protocolinfo = 0,
+ ACE_SOCK_GROUP g = 0,
+ u_long flags = 0,
+ int reuse_addr = 0);
+
+ /// Subscribe to the multicast interface using BSD-style semantics
+ /// (no QoS).
+ int subscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if,
+ int protocol_family,
+ int protocol,
+ int reuse_addr);
+
+ /// Unsubscribe to multicast interfaces subscribed to previously by
+ /// <subscribe_ifs>.
+ int unsubscribe_ifs (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = 0,
+ int protocol_family = PF_INET,
+ int protocol = 0);
+
+ // = Disable public use of <ACE_SOCK_Dgram::send>s
+
+ // This forces <ACE_SOCK_Dgram_Mcast::send>s inline.
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+ ssize_t send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags = 0) const;
+
+protected:
+ /// Initialize the <multicast_address_> IP address.
+ int make_multicast_address (const ACE_INET_Addr &mcast_addr,
+ const ACE_TCHAR *net_if = ACE_LIB_TEXT ("le0"));
+
+ /// Initialize a multicast address. This method factors out common
+ /// code called by <make_multicast_address> and <subscribe>.
+ int make_multicast_address_i (const ACE_INET_Addr &mcast_addr,
+ ip_mreq& multicast_address,
+ const ACE_TCHAR *net_if = ACE_LIB_TEXT ("le0"));
+
+ /// A copy of the address that we use to <send> multicasts.
+ ACE_INET_Addr mcast_addr_;
+
+ /// IP address of the interface upon which we're receiving
+ /// multicasts.
+ ip_mreq mcast_request_if_;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Dgram_Mcast.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_DGRAM_MCAST_H */
diff --git a/ace/Sockets/SOCK_Dgram_Mcast.i b/ace/Sockets/SOCK_Dgram_Mcast.i
new file mode 100644
index 00000000000..b7a9ca06abe
--- /dev/null
+++ b/ace/Sockets/SOCK_Dgram_Mcast.i
@@ -0,0 +1,78 @@
+/* -*- C++ -*- */
+// $Id$
+
+ASYS_INLINE
+ACE_SOCK_Dgram_Mcast::~ACE_SOCK_Dgram_Mcast (void)
+{
+}
+
+ASYS_INLINE int
+ACE_SOCK_Dgram_Mcast::set_option (int option,
+ char optval)
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::set_option");
+#if defined (ACE_WIN32)
+ int sock_opt = optval;
+ return this->ACE_SOCK::set_option (IPPROTO_IP,
+ option,
+ &sock_opt,
+ sizeof (sock_opt));
+#else
+ return this->ACE_SOCK::set_option (IPPROTO_IP,
+ option,
+ &optval,
+ sizeof (optval));
+#endif /* !ACE_WIN32 */
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast::send (const void *buf,
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
+ return this->ACE_SOCK_Dgram::send (buf,
+ n,
+ this->mcast_addr_,
+ flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast::send (const iovec iov[],
+ size_t n,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
+ return this->ACE_SOCK_Dgram::send (iov,
+ n,
+ this->mcast_addr_,
+ flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast::send (const void *buf,
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
+ return this->ACE_SOCK_Dgram::send (buf,
+ n,
+ addr,
+ flags);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Dgram_Mcast::send (const iovec iov[],
+ size_t n,
+ const ACE_Addr &addr,
+ int flags) const
+{
+ ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send");
+ return this->ACE_SOCK_Dgram::send (iov,
+ n,
+ addr,
+ flags);
+}
+
+
diff --git a/ace/Sockets/SOCK_IO.cpp b/ace/Sockets/SOCK_IO.cpp
new file mode 100644
index 00000000000..1f233aa88db
--- /dev/null
+++ b/ace/Sockets/SOCK_IO.cpp
@@ -0,0 +1,157 @@
+// SOCK_IO.cpp
+// $Id$
+
+#include "ace/SOCK_IO.h"
+#include "ace/Handle_Set.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_IO.i"
+#endif /* ACE_LACKS_INLINE_FUNCTIONS */
+
+ACE_RCSID(ace, SOCK_IO, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_IO)
+
+void
+ACE_SOCK_IO::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::dump");
+}
+
+// Allows a client to read from a socket without having to provide
+// a buffer to read. This method determines how much data is in the
+// socket, allocates a buffer of this size, reads in the data, and
+// returns the number of bytes read.
+
+ssize_t
+ACE_SOCK_IO::recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recvv");
+#if defined (FIONREAD)
+ ACE_Handle_Set handle_set;
+ handle_set.reset ();
+ handle_set.set_bit (this->get_handle ());
+
+ io_vec->iov_base = 0;
+
+ // Check the status of the current socket.
+ switch (ACE_OS::select (int (this->get_handle ()) + 1,
+ handle_set,
+ 0, 0,
+ timeout))
+ {
+ case -1:
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ errno = ETIME;
+ return -1;
+ /* NOTREACHED */
+ default:
+ // Goes fine, fallthrough to get data
+ break;
+ }
+
+ u_long inlen;
+
+ if (ACE_OS::ioctl (this->get_handle (),
+ FIONREAD,
+ (u_long *) &inlen) == -1)
+ return -1;
+ else if (inlen > 0)
+ {
+ ACE_NEW_RETURN (io_vec->iov_base,
+ char[inlen],
+ -1);
+ io_vec->iov_len = this->recv (io_vec->iov_base,
+ inlen);
+ return io_vec->iov_len;
+ }
+ else
+ return 0;
+#else
+ ACE_UNUSED_ARG (io_vec);
+ ACE_UNUSED_ARG (timeout);
+ ACE_NOTSUP_RETURN (-1);
+#endif /* FIONREAD */
+}
+
+// Send N char *ptrs and int lengths. Note that the char *'s precede
+// the ints (basically, an varargs version of writev). The count N is
+// the *total* number of trailing arguments, *not* a couple of the
+// number of tuple pairs!
+
+ssize_t
+ACE_SOCK_IO::send (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::send");
+
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, ssize_t);
+ }
+
+ ssize_t result = ACE_OS::sendv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
+
+// This is basically an interface to ACE_OS::readv, that doesn't use
+// the struct iovec_Base explicitly. The ... can be passed as an arbitrary
+// number of (char *ptr, int len) tuples. However, the count N is the
+// *total* number of trailing arguments, *not* a couple of the number
+// of tuple pairs!
+
+ssize_t
+ACE_SOCK_IO::recv (size_t n, ...) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+
+ va_list argp;
+ size_t total_tuples = n / 2;
+ iovec *iovp;
+#if defined (ACE_HAS_ALLOCA)
+ iovp = (iovec *) alloca (total_tuples * sizeof (iovec));
+#else
+ ACE_NEW_RETURN (iovp,
+ iovec[total_tuples],
+ -1);
+#endif /* !defined (ACE_HAS_ALLOCA) */
+
+ va_start (argp, n);
+
+ for (size_t i = 0; i < total_tuples; i++)
+ {
+ iovp[i].iov_base = va_arg (argp, char *);
+ iovp[i].iov_len = va_arg (argp, ssize_t);
+ }
+
+ ssize_t result = ACE_OS::recvv (this->get_handle (),
+ iovp,
+ total_tuples);
+#if !defined (ACE_HAS_ALLOCA)
+ delete [] iovp;
+#endif /* !defined (ACE_HAS_ALLOCA) */
+ va_end (argp);
+ return result;
+}
diff --git a/ace/Sockets/SOCK_IO.h b/ace/Sockets/SOCK_IO.h
new file mode 100644
index 00000000000..0fbfee6203d
--- /dev/null
+++ b/ace/Sockets/SOCK_IO.h
@@ -0,0 +1,143 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_IO.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_IO_H
+#define ACE_SOCK_IO_H
+#include "ace/pre.h"
+
+#include "ace/SOCK.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_SOCK_IO
+ *
+ * @brief Defines the methods for the ACE socket wrapper I/O routines
+ * (e.g., send/recv).
+ *
+ *
+ * If <timeout> == 0, then the call behaves as a normal
+ * send/recv call, i.e., for blocking sockets, the call will
+ * block until action is possible; for non-blocking sockets,
+ * EWOULDBLOCK will be returned if no action is immediately
+ * possible.
+ * If <timeout> != 0, the call will wait until the relative time
+ * specified in *<timeout> elapses.
+ * Errors are reported by -1 and 0 return values. If the
+ * operation times out, -1 is returned with <errno == ETIME>.
+ * If it succeeds the number of bytes transferred is returned.
+ * Methods with the extra <flags> argument will always result in
+ * <send> getting called. Methods without the extra <flags>
+ * argument will result in <send> getting called on Win32
+ * platforms, and <write> getting called on non-Win32 platforms.
+ */
+class ACE_Export ACE_SOCK_IO : public ACE_SOCK
+{
+public:
+ // = Initialization and termination methods.
+
+ /// Constructor.
+ ACE_SOCK_IO (void);
+
+ /// Destructor.
+ ~ACE_SOCK_IO (void);
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an <n> byte buffer from the connected socket.
+ ssize_t recv (void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv an <iovec> of size <n> from the connected socket.
+ ssize_t recvv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Same as above. Deprecated.
+ ssize_t recv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /**
+ * Allows a client to read from a socket without having to provide a
+ * buffer to read. This method determines how much data is in the
+ * socket, allocates a buffer of this size, reads in the data, and
+ * returns the number of bytes read. The caller is responsible for
+ * deleting the member in the <iov_base> field of <io_vec> using
+ * delete [] io_vec->iov_base.
+ */
+ ssize_t recvv (iovec *io_vec,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Same as above. Deprecated.
+ ssize_t recv (iovec *io_vec,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Recv <n> varargs messages to the connected socket.
+ ssize_t recv (size_t n,
+ ...) const;
+
+ /// Recv <n> bytes via Win32 <ReadFile> using overlapped I/O.
+ ssize_t recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ int flags,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send an <n> byte buffer to the connected socket.
+ ssize_t send (const void *buf,
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send an <iovec> of size <n> to the connected socket.
+ ssize_t sendv (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Same as above. Deprecated.
+ ssize_t send (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout = 0) const;
+
+ /// Send <n> varargs messages to the connected socket.
+ ssize_t send (size_t n,
+ ...) const;
+
+ /// Send <n> bytes via Win32 <WriteFile> using overlapped I/O.
+ ssize_t send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_IO.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_IO_H */
diff --git a/ace/Sockets/SOCK_IO.i b/ace/Sockets/SOCK_IO.i
new file mode 100644
index 00000000000..d46ca3c188f
--- /dev/null
+++ b/ace/Sockets/SOCK_IO.i
@@ -0,0 +1,149 @@
+/* -*- C++ -*- */
+// $Id$
+
+// SOCK_IO.i
+
+// Send an n byte message to the connected socket.
+
+ASYS_INLINE
+ACE_SOCK_IO::ACE_SOCK_IO (void)
+{
+ // ACE_TRACE ("ACE_SOCK_IO::ACE_SOCK_IO");
+}
+
+ASYS_INLINE
+ACE_SOCK_IO::~ACE_SOCK_IO (void)
+{
+ // ACE_TRACE ("ACE_SOCK_IO::~ACE_SOCK_IO");
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recv (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+ return ACE::recv (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recv (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+ return ACE::recv (this->get_handle (),
+ buf,
+ len,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recvv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recvv");
+ return ACE::recvv (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recv (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+ return this->recvv (iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recv (iovec *io_vec,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+ return this->recvv (io_vec,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::recv (void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::recv");
+ return ACE_OS::read (this->get_handle (),
+ (char *) buf,
+ n,
+ overlapped);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::send (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::send");
+ return ACE::send (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::send (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::send");
+ return ACE::send (this->get_handle (),
+ buf,
+ len,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::sendv (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::sendv");
+ return ACE::sendv (this->get_handle (),
+ iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::send (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::send");
+ return this->sendv (iov,
+ n,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_IO::send (const void *buf,
+ size_t n,
+ ACE_OVERLAPPED *overlapped) const
+{
+ ACE_TRACE ("ACE_SOCK_IO::send");
+ return ACE_OS::write (this->get_handle (),
+ (const char *) buf,
+ n,
+ overlapped);
+}
diff --git a/ace/Sockets/SOCK_Stream.cpp b/ace/Sockets/SOCK_Stream.cpp
new file mode 100644
index 00000000000..cd9be127aaa
--- /dev/null
+++ b/ace/Sockets/SOCK_Stream.cpp
@@ -0,0 +1,35 @@
+// SOCK_Stream.cpp
+// $Id$
+
+#include "ace/SOCK_Stream.h"
+
+#if defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Stream.i"
+#endif
+
+ACE_RCSID(ace, SOCK_Stream, "$Id$")
+
+ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Stream)
+
+void
+ACE_SOCK_Stream::dump (void) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::dump");
+}
+
+int
+ACE_SOCK_Stream::close (void)
+{
+#if defined (ACE_WIN32)
+ // We need the following call to make things work correctly on
+ // Win32, which requires use to do a <close_writer> before doing the
+ // close in order to avoid losing data. Note that we don't need to
+ // do this on UNIX since it doesn't have this "feature". Moreover,
+ // this will cause subtle problems on UNIX due to the way that
+ // fork() works.
+ this->close_writer ();
+#endif /* ACE_WIN32 */
+ // Close down the socket.
+ return ACE_SOCK::close ();
+}
+
diff --git a/ace/Sockets/SOCK_Stream.h b/ace/Sockets/SOCK_Stream.h
new file mode 100644
index 00000000000..f478702aaaa
--- /dev/null
+++ b/ace/Sockets/SOCK_Stream.h
@@ -0,0 +1,167 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file SOCK_Stream.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SOCK_STREAM_H
+#define ACE_SOCK_STREAM_H
+#include "ace/pre.h"
+
+#include "ace/SOCK_IO.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+
+// Forward declarations.
+class ACE_Message_Block;
+
+/**
+ * @class ACE_SOCK_Stream
+ *
+ * @brief Defines the methods in the <ACE_SOCK_Stream> abstraction.
+ *
+ * This adds additional wrapper methods atop the <ACE_SOCK_IO>
+ * class.
+ *
+ * <buf> is the buffer to write from or receive into.
+ * <len> is the number of bytes to transfer.
+ * The <timeout> parameter in the following methods indicates how
+ * long to blocking trying to transfer data. If <timeout> == 0,
+ * then the call behaves as a normal send/recv call, i.e., for
+ * blocking sockets, the call will block until action is possible;
+ * for non-blocking sockets, EWOULDBLOCK will be returned if no
+ * action is immediately possible.
+ * If <timeout> != 0, the call will wait for data to arrive no longer
+ * than the relative time specified in *<timeout>.
+ * The "_n()" I/O methods keep looping until all the data has been
+ * transferred. These methods also work for sockets in non-blocking
+ * mode i.e., they keep looping on EWOULDBLOCK. <timeout> is used
+ * to make sure we keep making progress, i.e., the same timeout
+ * value is used for every I/O operation in the loop and the timeout
+ * is not counted down.
+ * The return values for the "*_n()" methods match the return values
+ * from the non "_n()" methods and are specified as follows:
+ * - On complete transfer, the number of bytes transferred is returned.
+ * - On timeout, -1 is returned, errno == ETIME.
+ * - On error, -1 is returned, errno is set to appropriate error.
+ * - On EOF, 0 is returned, errno is irrelevant.
+ *
+ * On partial transfers, i.e., if any data is transferred before
+ * timeout/error/EOF, <bytes_transferred> will contain the number of
+ * bytes transferred.
+ * Methods with <iovec> parameter are I/O vector variants of the I/O
+ * operations.
+ * Methods with the extra <flags> argument will always result in
+ * <send> getting called. Methods without the extra <flags> argument
+ * will result in <send> getting called on Win32 platforms, and
+ * <write> getting called on non-Win32 platforms.
+ */
+class ACE_Export ACE_SOCK_Stream : public ACE_SOCK_IO
+{
+public:
+ // Initialization and termination methods.
+ /// Constructor.
+ ACE_SOCK_Stream (void);
+
+ /// Constructor (sets the underlying <ACE_HANDLE> with <h>).
+ ACE_SOCK_Stream (ACE_HANDLE h);
+
+ /// Destructor.
+ ~ACE_SOCK_Stream (void);
+
+ // = I/O functions.
+
+ /// Try to recv exactly <len> bytes into <buf> from the connected socket.
+ ssize_t recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to recv exactly <len> bytes into <buf> from the connected socket.
+ ssize_t recv_n (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Receive an <iovec> of size <iovcnt> from the connected socket.
+ ssize_t recvv_n (iovec iov[],
+ size_t iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly <len> bytes from <buf> to the connection socket.
+ ssize_t send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Try to send exactly <len> bytes from <buf> to the connected socket.
+ ssize_t send_n (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Send all the <message_block>s chained through their <next> and
+ /// <cont> pointers. This call uses the underlying OS gather-write
+ /// operation to reduce the domain-crossing penalty.
+ ssize_t send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ /// Send an <iovec> of size <iovcnt> to the connected socket.
+ ssize_t sendv_n (const iovec iov[],
+ size_t iovcnt,
+ const ACE_Time_Value *timeout = 0,
+ size_t *bytes_transferred = 0) const;
+
+ // = Send/receive ``urgent'' data (see TCP specs...).
+ ssize_t send_urg (const void *ptr,
+ size_t len = sizeof (char),
+ const ACE_Time_Value *timeout = 0) const;
+
+ ssize_t recv_urg (void *ptr,
+ size_t len = sizeof (char),
+ const ACE_Time_Value *timeout = 0) const;
+
+ // = Selectively close endpoints.
+ /// Close down the reader.
+ int close_reader (void);
+
+ /// Close down the writer.
+ int close_writer (void);
+
+ /**
+ * Close down the socket (we need this to make things work correctly
+ * on Win32, which requires use to do a <close_writer> before doing
+ * the close to avoid losing data).
+ */
+ int close (void);
+
+ // = Meta-type info
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+};
+
+#if !defined (ACE_LACKS_INLINE_FUNCTIONS)
+#include "ace/SOCK_Stream.i"
+#endif
+
+#include "ace/post.h"
+#endif /* ACE_SOCK_STREAM_H */
diff --git a/ace/Sockets/SOCK_Stream.i b/ace/Sockets/SOCK_Stream.i
new file mode 100644
index 00000000000..0684e069832
--- /dev/null
+++ b/ace/Sockets/SOCK_Stream.i
@@ -0,0 +1,171 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/SOCK_Stream.h"
+
+ASYS_INLINE
+ACE_SOCK_Stream::ACE_SOCK_Stream (void)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::ACE_SOCK_Stream");
+}
+
+ASYS_INLINE
+ACE_SOCK_Stream::ACE_SOCK_Stream (ACE_HANDLE h)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::ACE_SOCK_Stream");
+ this->set_handle (h);
+}
+
+ASYS_INLINE
+ACE_SOCK_Stream::~ACE_SOCK_Stream (void)
+{
+ // ACE_TRACE ("ACE_SOCK_Stream::~ACE_SOCK_Stream");
+}
+
+ASYS_INLINE int
+ACE_SOCK_Stream::close_reader (void)
+{
+ ACE_TRACE ("ACE_SOCK_Stream::close_reader");
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return ACE_OS::shutdown (this->get_handle (), ACE_SHUTDOWN_READ);
+ else
+ return 0;
+}
+
+// Shut down just the writing end of a ACE_SOCK.
+
+ASYS_INLINE int
+ACE_SOCK_Stream::close_writer (void)
+{
+ ACE_TRACE ("ACE_SOCK_Stream::close_writer");
+ if (this->get_handle () != ACE_INVALID_HANDLE)
+ return ACE_OS::shutdown (this->get_handle (), ACE_SHUTDOWN_WRITE);
+ else
+ return 0;
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::recv_n (void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::recv_n (void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::recv_n");
+ return ACE::recv_n (this->get_handle (),
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::recvv_n (iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::recvv_n");
+ return ACE::recvv_n (this->get_handle (),
+ iov,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::send_n (const void *buf,
+ size_t len,
+ int flags,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ flags,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::send_n (const void *buf,
+ size_t len,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ buf,
+ len,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::sendv_n (const iovec iov[],
+ size_t n,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::sendv_n");
+ return ACE::sendv_n (this->get_handle (),
+ iov,
+ n,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::send_n (const ACE_Message_Block *message_block,
+ const ACE_Time_Value *timeout,
+ size_t *bytes_transferred) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::send_n");
+ return ACE::send_n (this->get_handle (),
+ message_block,
+ timeout,
+ bytes_transferred);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::send_urg (const void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::send_urg");
+ return ACE::send (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
+
+ASYS_INLINE ssize_t
+ACE_SOCK_Stream::recv_urg (void *ptr,
+ size_t len,
+ const ACE_Time_Value *timeout) const
+{
+ ACE_TRACE ("ACE_SOCK_Stream::recv_urg");
+ return ACE::recv (this->get_handle (),
+ ptr,
+ len,
+ MSG_OOB,
+ timeout);
+}
diff --git a/ace/Streams/CDR_Base.cpp b/ace/Streams/CDR_Base.cpp
new file mode 100644
index 00000000000..f505822303f
--- /dev/null
+++ b/ace/Streams/CDR_Base.cpp
@@ -0,0 +1,585 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/CDR_Base.h"
+#include "ace/Message_Block.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/CDR_Base.inl"
+#endif /* ! __ACE_INLINE__ */
+
+ACE_RCSID(ace, CDR_Base, "$Id$")
+
+
+//
+// See comments in CDR_Base.i about optimization cases for swap_XX_array.
+//
+
+void
+ACE_CDR::swap_2_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ // Later, we try to read in 32 or 64 bit chunks,
+ // so make sure we don't do that for unaligned addresses.
+#if ACE_SIZEOF_LONG == 8
+ const char* const o8 = ACE_ptr_align_binary(orig, 8);
+ while (orig < o8 && n > 0)
+ {
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ --n;
+ }
+#else
+ const char* const o4 = ACE_ptr_align_binary(orig, 4);
+ // this is an _if_, not a _while_. The mistmatch can only be by 2.
+ if (orig != o4)
+ {
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ --n;
+ }
+#endif
+ if (n == 0)
+ return;
+
+ //
+ // Loop unrolling. Here be dragons.
+ //
+
+ // (n & (~3)) is the greatest multiple of 4 not bigger than n.
+ // In the while loop ahead, orig will move over the array by 8 byte
+ // increments (4 elements of 2 bytes).
+ // end marks our barrier for not falling outside.
+ const char* const end = orig + 2*(n & (~3));
+
+ // See if we're aligned for writting in 64 or 32 bit chunks...
+#if ACE_SIZEOF_LONG == 8
+ if (target == ACE_ptr_align_binary(target, 8))
+#else
+ if (target == ACE_ptr_align_binary(target, 4))
+#endif
+ {
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ unsigned int a =
+ * ACE_reinterpret_cast(const unsigned int*, orig);
+ unsigned int b =
+ * ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ asm( "bswap %1" : "=r" (a) : "0" (a) );
+ asm( "bswap %1" : "=r" (b) : "0" (b) );
+ asm( "rol $16, %1" : "=r" (a) : "0" (a) );
+ asm( "rol $16, %1" : "=r" (b) : "0" (b) );
+ * ACE_reinterpret_cast(unsigned int*, target) = a;
+ * ACE_reinterpret_cast(unsigned int*, target + 4) = b;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ __asm rol eax, 16;
+ __asm rol ebx, 16;
+ __asm mov [edx], eax;
+ __asm mov 4[edx], ebx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long a =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+
+ register unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
+ register unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
+
+ a = (a1 | a2);
+
+ * ACE_reinterpret_cast(unsigned long*, target) = a;
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+
+ register ACE_UINT32 a1 = (a & 0x00ff00ffU) << 8;
+ register ACE_UINT32 b1 = (b & 0x00ff00ffU) << 8;
+ register ACE_UINT32 a2 = (a & 0xff00ff00U) >> 8;
+ register ACE_UINT32 b2 = (b & 0xff00ff00U) >> 8;
+
+ a = (a1 | a2);
+ b = (b1 | b2);
+
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = a;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = b;
+#endif
+ orig += 8;
+ target += 8;
+ }
+ }
+ else
+ {
+ // We're out of luck. We have to write in 2 byte chunks.
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ unsigned int a =
+ * ACE_reinterpret_cast(const unsigned int*, orig);
+ unsigned int b =
+ * ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ asm( "bswap %1" : "=r" (a) : "0" (a) );
+ asm( "bswap %1" : "=r" (b) : "0" (b) );
+ // We're little endian.
+ * ACE_reinterpret_cast(unsigned short*, target + 2)
+ = (unsigned short) (a & 0xffff);
+ * ACE_reinterpret_cast(unsigned short*, target + 6)
+ = (unsigned short) (b & 0xffff);
+ asm( "shrl $16, %1" : "=r" (a) : "0" (a) );
+ asm( "shrl $16, %1" : "=r" (b) : "0" (b) );
+ * ACE_reinterpret_cast(unsigned short*, target + 0)
+ = (unsigned short) (a & 0xffff);
+ * ACE_reinterpret_cast(unsigned short*, target + 4)
+ = (unsigned short) (b & 0xffff);
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ // We're little endian.
+ __asm mov 2[edx], ax;
+ __asm mov 6[edx], bx;
+ __asm shr eax, 16;
+ __asm shr ebx, 16;
+ __asm mov 0[edx], ax;
+ __asm mov 4[edx], bx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long a =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+
+ register unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
+ register unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
+
+ a = (a1 | a2);
+
+ ACE_UINT16 b1 = ACE_static_cast(ACE_UINT16, (a >> 48));
+ ACE_UINT16 b2 = ACE_static_cast(ACE_UINT16, ((a >> 32) & 0xffff));
+ ACE_UINT16 b3 = ACE_static_cast(ACE_UINT16, ((a >> 16) & 0xffff));
+ ACE_UINT16 b4 = ACE_static_cast(ACE_UINT16, (a & 0xffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = b4;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = b3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = b2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = b1;
+#else
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = b1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = b2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = b3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = b4;
+#endif
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+
+ register ACE_UINT32 a1 = (a & 0x00ff00ff) << 8;
+ register ACE_UINT32 b1 = (b & 0x00ff00ff) << 8;
+ register ACE_UINT32 a2 = (a & 0xff00ff00) >> 8;
+ register ACE_UINT32 b2 = (b & 0xff00ff00) >> 8;
+
+ a = (a1 | a2);
+ b = (b1 | b2);
+
+ ACE_UINT32 c1 = ACE_static_cast(ACE_UINT16, (a >> 16));
+ ACE_UINT32 c2 = ACE_static_cast(ACE_UINT16, (a & 0xffff));
+ ACE_UINT32 c3 = ACE_static_cast(ACE_UINT16, (b >> 16));
+ ACE_UINT32 c4 = ACE_static_cast(ACE_UINT16, (b & 0xffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = c2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = c1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = c4;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = c3;
+#else
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = c1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = c2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = c3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = c4;
+#endif
+#endif
+
+ orig += 8;
+ target += 8;
+ }
+ }
+
+ // (n & 3) == (n % 4).
+ switch (n&3) {
+ case 3:
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ case 2:
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ case 1:
+ ACE_CDR::swap_2 (orig, target);
+ }
+}
+
+void
+ACE_CDR::swap_4_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+#if ACE_LONG_SIZE == 8
+ // Later, we read from *orig in 64 bit chunks,
+ // so make sure we don't generate unaligned readings.
+ const char* const o8 = ACE_ptr_align_binary(orig, 8);
+ // The mistmatch can only be by 4.
+ if (orig != o8)
+ {
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ --n;
+ }
+#endif
+ if (n == 0)
+ return;
+
+ //
+ // Loop unrolling. Here be dragons.
+ //
+
+ // (n & (~3)) is the greatest multiple of 4 not bigger than n.
+ // In the while loop, orig will move over the array by 16 byte
+ // increments (4 elements of 4 bytes).
+ // ends marks our barrier for not falling outside.
+ const char* const end = orig + 4*(n & (~3));
+
+#if ACE_LONG_SIZE == 8
+ // 64 bits architecture.
+ // See if we can write in 8 byte chunks.
+ if (target == ACE_ptr_align_binary(target, 8))
+ {
+ while (orig < end)
+ {
+ register unsigned long a =
+ * ACE_reinterpret_cast(const long*, orig);
+ register unsigned long b =
+ * ACE_reinterpret_cast(const long*, orig + 8);
+
+ register unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
+ register unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
+ register unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
+ register unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
+ register unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
+ register unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
+ register unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
+ register unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
+
+ a = (a84 | a73 | a62 | a51);
+ b = (b84 | b73 | b62 | b51);
+
+ * ACE_reinterpret_cast(long*, target) = a;
+ * ACE_reinterpret_cast(long*, target + 8) = b;
+
+ orig += 16;
+ target += 16;
+ }
+ }
+ else
+ {
+ // We are out of luck, we have to write in 4 byte chunks.
+ while (orig < end)
+ {
+ register unsigned long a =
+ * ACE_reinterpret_cast(const long*, orig);
+ register unsigned long b =
+ * ACE_reinterpret_cast(const long*, orig + 8);
+
+ register unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
+ register unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
+ register unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
+ register unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
+ register unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
+ register unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
+ register unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
+ register unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
+
+ a = (a84 | a73 | a62 | a51);
+ b = (b84 | b73 | b62 | b51);
+
+ ACE_UINT32 c1 = ACE_static_cast(ACE_UINT32, (a >> 32));
+ ACE_UINT32 c2 = ACE_static_cast(ACE_UINT32, (a & 0xffffffff));
+ ACE_UINT32 c3 = ACE_static_cast(ACE_UINT32, (b >> 32));
+ ACE_UINT32 c4 = ACE_static_cast(ACE_UINT32, (b & 0xffffffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 0) = c2;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = c1;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c4;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = c3;
+#else
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 0) = c1;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = c2;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c3;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = c4;
+#endif
+ orig += 16;
+ target += 16;
+ }
+ }
+
+#else /* ACE_LONG_SIZE != 8 */
+
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ register unsigned int a =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ register unsigned int b =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ register unsigned int c =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 8);
+ register unsigned int d =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 12);
+
+ asm ("bswap %1" : "=r" (a) : "0" (a));
+ asm ("bswap %1" : "=r" (b) : "0" (b));
+ asm ("bswap %1" : "=r" (c) : "0" (c));
+ asm ("bswap %1" : "=r" (d) : "0" (d));
+
+ *ACE_reinterpret_cast(unsigned int*, target) = a;
+ *ACE_reinterpret_cast(unsigned int*, target + 4) = b;
+ *ACE_reinterpret_cast(unsigned int*, target + 8) = c;
+ *ACE_reinterpret_cast(unsigned int*, target + 12) = d;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov eax, orig
+ __asm mov esi, target
+ __asm mov edx, [eax]
+ __asm mov ecx, 4[eax]
+ __asm mov ebx, 8[eax]
+ __asm mov eax, 12[eax]
+ __asm bswap edx
+ __asm bswap ecx
+ __asm bswap ebx
+ __asm bswap eax
+ __asm mov [esi], edx
+ __asm mov 4[esi], ecx
+ __asm mov 8[esi], ebx
+ __asm mov 12[esi], eax
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+ register ACE_UINT32 c =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 8);
+ register ACE_UINT32 d =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 12);
+
+ // Expect the optimizer reordering this A LOT.
+ // We leave it this way for clarity.
+ a = (a << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) | (a >> 24);
+ b = (b << 24) | ((b & 0xff00) << 8) | ((b & 0xff0000) >> 8) | (b >> 24);
+ c = (c << 24) | ((c & 0xff00) << 8) | ((c & 0xff0000) >> 8) | (c >> 24);
+ d = (d << 24) | ((d & 0xff00) << 8) | ((d & 0xff0000) >> 8) | (d >> 24);
+
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = a;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = b;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = d;
+#endif
+
+ orig += 16;
+ target += 16;
+ }
+
+#endif /* ACE_LONG_SIZE == 8 */
+
+ // (n & 3) == (n % 4).
+ switch (n&3) {
+ case 3:
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ case 2:
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ case 1:
+ ACE_CDR::swap_4 (orig, target);
+ }
+}
+
+//
+// We don't benefit from unrolling in swap_8_array and swap_16_array
+// (swap_8 and swap_16 are big enough).
+//
+void
+ACE_CDR::swap_8_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ const char* const end = orig + 8*n;
+ while (orig < end)
+ {
+ swap_8(orig, target);
+ orig += 8;
+ target += 8;
+ }
+}
+
+void
+ACE_CDR::swap_16_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ const char* const end = orig + 16*n;
+ while (orig < end)
+ {
+ swap_16(orig, target);
+ orig += 16;
+ target += 16;
+ }
+}
+
+int
+ACE_CDR::grow (ACE_Message_Block *mb, size_t minsize)
+{
+ size_t newsize =
+ ACE_CDR::first_size (minsize + ACE_CDR::MAX_ALIGNMENT);
+
+ if (newsize <= mb->size ())
+ return 0;
+
+ ACE_Data_Block *db =
+ mb->data_block ()->clone_nocopy ();
+
+ if (db->size (newsize) == -1)
+ return -1;
+
+ ACE_Message_Block tmp (db);
+ ACE_CDR::mb_align (&tmp);
+
+ tmp.copy (mb->rd_ptr (), mb->length());
+ mb->data_block (tmp.data_block ()->duplicate ());
+ mb->rd_ptr (tmp.rd_ptr ());
+ mb->wr_ptr (tmp.wr_ptr ());
+
+ // Remove the DONT_DELETE flags from mb
+ mb->clr_self_flags (ACE_Message_Block::DONT_DELETE);
+
+ return 0;
+}
+
+size_t
+ACE_CDR::total_length (const ACE_Message_Block* begin,
+ const ACE_Message_Block* end)
+{
+ size_t l = 0;
+ // Compute the total size.
+ for (const ACE_Message_Block *i = begin;
+ i != end;
+ i = i->cont ())
+ l += i->length ();
+ return l;
+}
+
+void
+ACE_CDR::consolidate (ACE_Message_Block *dst,
+ const ACE_Message_Block *src)
+{
+ if (src == 0)
+ return;
+
+ size_t newsize =
+ ACE_CDR::first_size (ACE_CDR::total_length (src, 0)
+ + ACE_CDR::MAX_ALIGNMENT);
+ dst->size (newsize);
+
+ // We must copy the contents of <src> into the new buffer, but
+ // respecting the alignment.
+ ptr_arith_t srcalign =
+ ptr_arith_t(src->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ ptr_arith_t dstalign =
+ ptr_arith_t(dst->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ int offset = srcalign - dstalign;
+ if (offset < 0)
+ offset += ACE_CDR::MAX_ALIGNMENT;
+ dst->rd_ptr (offset);
+ dst->wr_ptr (dst->rd_ptr ());
+
+ for (const ACE_Message_Block* i = src;
+ i != 0;
+ i = i->cont ())
+ {
+ dst->copy (i->rd_ptr (), i->length ());
+ }
+}
+
+#if defined (NONNATIVE_LONGLONG)
+int
+ACE_CDR::LongLong::operator== (const ACE_CDR::LongLong &rhs) const
+{
+ return this->h == rhs.h && this->l == rhs.l;
+}
+
+int
+ACE_CDR::LongLong::operator!= (const ACE_CDR::LongLong &rhs) const
+{
+ return this->l != rhs.l || this->h != rhs.h;
+}
+#endif /* NONNATIVE_LONGLONG */
+
+#if defined (NONNATIVE_LONGDOUBLE)
+int
+ACE_CDR::LongDouble::operator== (const ACE_CDR::LongDouble &rhs) const
+{
+ return ACE_OS::memcmp (this->ld, rhs.ld, 16) == 0;
+}
+
+int
+ACE_CDR::LongDouble::operator!= (const ACE_CDR::LongDouble &rhs) const
+{
+ return ACE_OS::memcmp (this->ld, rhs.ld, 16) != 0;
+}
+#endif /* NONNATIVE_LONGDOUBLE */
+
+#if defined(_UNICOS) && !defined(_CRAYMPP)
+// placeholders to get things compiling
+ACE_CDR::Float::Float()
+{
+}
+
+ACE_CDR::Float::Float(const float & init)
+{
+}
+
+ACE_CDR::Float &
+ACE_CDR::Float::operator= (const float &rhs)
+{
+ return *this;
+}
+
+int
+ACE_CDR::Float::operator!= (const ACE_CDR::Float &rhs) const
+{
+ return 0;
+}
+#endif /* _UNICOS */
diff --git a/ace/Streams/CDR_Base.h b/ace/Streams/CDR_Base.h
new file mode 100644
index 00000000000..884fd196e25
--- /dev/null
+++ b/ace/Streams/CDR_Base.h
@@ -0,0 +1,291 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file CDR_Base.h
+ *
+ * $Id$
+ *
+ * ACE Common Data Representation (CDR) basic types.
+ *
+ * The current implementation assumes that the host has 1-byte,
+ * 2-byte and 4-byte integral types, and that it has single
+ * precision and double precision IEEE floats.
+ * Those assumptions are pretty good these days, with Crays being
+ * the only known exception.
+ *
+ *
+ * @author TAO version by
+ * @author Aniruddha Gokhale <gokhale@cs.wustl.edu>
+ * @author Carlos O'Ryan<coryan@cs.wustl.edu>
+ * @author ACE version by
+ * @author Jeff Parsons <parsons@cs.wustl.edu>
+ * @author Istvan Buki <istvan.buki@euronet.be>
+ */
+//=============================================================================
+
+
+#ifndef ACE_CDR_BASE_H
+#define ACE_CDR_BASE_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Basic_Types.h"
+#include "ace/Message_Block.h"
+
+/**
+ * @class ACE_CDR
+ *
+ * @brief Keep constants and some routines common to both Output and
+ * Input CDR streams.
+ */
+class ACE_Export ACE_CDR
+{
+public:
+ // = Constants defined by the CDR protocol.
+ // By defining as many of these constants as possible as enums we
+ // ensure they get inlined and avoid pointless static memory
+ // allocations.
+
+ enum
+ {
+ // Note that some of these get reused as part of the standard
+ // binary format: unsigned is the same size as its signed cousin,
+ // float is LONG_SIZE, and double is LONGLONG_SIZE.
+
+ OCTET_SIZE = 1,
+ SHORT_SIZE = 2,
+ LONG_SIZE = 4,
+ LONGLONG_SIZE = 8,
+ LONGDOUBLE_SIZE = 16,
+
+ OCTET_ALIGN = 1,
+ SHORT_ALIGN = 2,
+ LONG_ALIGN = 4,
+ LONGLONG_ALIGN = 8,
+ /// @note the CORBA LongDouble alignment requirements do not
+ /// match its size...
+ LONGDOUBLE_ALIGN = 8,
+
+ /// Maximal CDR 1.1 alignment: "quad precision" FP (i.e. "CDR::Long
+ /// double", size as above).
+ MAX_ALIGNMENT = 8,
+
+ /// The default buffer size.
+ /**
+ * @todo We want to add options to control this
+ * default value, so this constant should be read as the default
+ * default value ;-)
+ */
+ DEFAULT_BUFSIZE = ACE_DEFAULT_CDR_BUFSIZE,
+
+ /// The buffer size grows exponentially until it reaches this size;
+ /// afterwards it grows linearly using the next constant
+ EXP_GROWTH_MAX = ACE_DEFAULT_CDR_EXP_GROWTH_MAX,
+
+ /// Once exponential growth is ruled out the buffer size increases
+ /// in chunks of this size, note that this constants have the same
+ /// value right now, but it does not need to be so.
+ LINEAR_GROWTH_CHUNK = ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK
+ };
+
+ /**
+ * Do byte swapping for each basic IDL type size. There exist only
+ * routines to put byte, halfword (2 bytes), word (4 bytes),
+ * doubleword (8 bytes) and quadword (16 byte); because those are
+ * the IDL basic type sizes.
+ */
+ static void swap_2 (const char *orig, char *target);
+ static void swap_4 (const char *orig, char *target);
+ static void swap_8 (const char *orig, char *target);
+ static void swap_16 (const char *orig, char *target);
+ static void swap_2_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_4_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_8_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_16_array (const char *orig,
+ char *target,
+ size_t length);
+
+ /// Align the message block to ACE_CDR::MAX_ALIGNMENT,
+ /// set by the CORBA spec at 8 bytes.
+ static void mb_align (ACE_Message_Block *mb);
+
+ /**
+ * Compute the size of the smallest buffer that can contain at least
+ * <minsize> bytes.
+ * To understand how a "best fit" is computed look at the
+ * algorithm in the code.
+ * Basically the buffers grow exponentially, up to a certain point,
+ * then the buffer size grows linearly.
+ * The advantage of this algorithm is that is rapidly grows to a
+ * large value, but does not explode at the end.
+ */
+ static size_t first_size (size_t minsize);
+
+ /// Compute not the smallest, but the second smallest buffer that
+ /// will fir <minsize> bytes.
+ static size_t next_size (size_t minsize);
+
+ /**
+ * Increase the capacity of mb to contain at least <minsize> bytes.
+ * If <minsize> is zero the size is increased by an amount at least
+ * large enough to contain any of the basic IDL types. Return -1 on
+ * failure, 0 on success.
+ */
+ static int grow (ACE_Message_Block *mb, size_t minsize);
+
+ /// Copy a message block chain into a single message block,
+ /// preserving the alignment of the original stream.
+ static void consolidate (ACE_Message_Block *dst,
+ const ACE_Message_Block *src);
+
+ static size_t total_length (const ACE_Message_Block *begin,
+ const ACE_Message_Block *end);
+
+ // Definitions of the IDL basic types, for use in the CDR
+ // classes. The cleanest way to avoid complaints from all compilers
+ // is to define them all.
+ #if defined (CHORUS) && defined (ghs) && !defined (__STANDARD_CXX)
+ // This is non-compliant, but a nasty bout with
+ // Green Hills C++68000 1.8.8 forces us into it.
+ typedef unsigned long Boolean;
+ #else /* ! (CHORUS && ghs 1.8.8) */
+ typedef u_char Boolean;
+ #endif /* ! (CHORUS && ghs 1.8.8) */
+
+ typedef u_char Octet;
+ typedef char Char;
+ typedef ACE_OS::WChar WChar;
+ typedef ACE_INT16 Short;
+ typedef ACE_UINT16 UShort;
+ typedef ACE_INT32 Long;
+ typedef ACE_UINT32 ULong;
+ typedef ACE_UINT64 ULongLong;
+
+ # if (defined (_MSC_VER) && (_MSC_VER >= 900)) \
+ || (defined (__BORLANDC__) && (__BORLANDC__ >= 0x530))
+ typedef __int64 LongLong;
+ # elif ACE_SIZEOF_LONG == 8 && !defined(_CRAYMPP)
+ typedef long LongLong;
+ # elif ACE_SIZEOF_LONG_LONG == 8 && !defined (ACE_LACKS_LONGLONG_T)
+ # if defined (sun) && !defined (ACE_LACKS_U_LONGLONG_T) && !defined (__KCC)
+ // sun #defines u_longlong_t, maybe other platforms do also.
+ // Use it, at least with g++, so that its -pedantic doesn't
+ // complain about no ANSI C++ long long.
+ typedef longlong_t LongLong;
+ # else
+ // LynxOS 2.5.0 and Linux don't have u_longlong_t.
+ typedef long long LongLong;
+ # endif /* sun */
+ # else /* no native 64 bit integer type */
+ # define NONNATIVE_LONGLONG
+ # if defined (ACE_BIG_ENDIAN)
+ struct ACE_Export LongLong
+ {
+ ACE_CDR::Long h;
+ ACE_CDR::Long l;
+ int operator== (const LongLong &rhs) const;
+ int operator!= (const LongLong &rhs) const;
+ };
+ # else
+ struct ACE_Export LongLong
+ {
+ ACE_CDR::Long l;
+ ACE_CDR::Long h;
+ int operator== (const LongLong &rhs) const;
+ int operator!= (const LongLong &rhs) const;
+ };
+ # endif /* ! ACE_BIG_ENDIAN */
+ # endif /* no native 64 bit integer type */
+
+ # if defined (NONNATIVE_LONGLONG)
+ # define ACE_CDR_LONGLONG_INITIALIZER {0,0}
+ # else
+ # define ACE_CDR_LONGLONG_INITIALIZER 0
+ # endif /* NONNATIVE_LONGLONG */
+
+ # if ACE_SIZEOF_FLOAT == 4
+ typedef float Float;
+ # else /* ACE_SIZEOF_FLOAT != 4 */
+ struct Float
+ {
+ # if ACE_SIZEOF_INT == 4
+ // Use u_int to get word alignment.
+ u_int f;
+ # else /* ACE_SIZEOF_INT != 4 */
+ // Applications will probably have trouble with this.
+ char f[4];
+ # if defined(_UNICOS) && !defined(_CRAYMPP)
+ Float (void);
+ Float (const float &init);
+ Float & operator= (const float &rhs);
+ int operator!= (const Float &rhs) const;
+ # endif /* _UNICOS */
+ # endif /* ACE_SIZEOF_INT != 4 */
+ };
+ # endif /* ACE_SIZEOF_FLOAT != 4 */
+
+ # if ACE_SIZEOF_DOUBLE == 8
+ typedef double Double;
+ # else /* ACE_SIZEOF_DOUBLE != 8 */
+ struct Double
+ {
+ # if ACE_SIZEOF_LONG == 8
+ // Use u_long to get word alignment.
+ u_long f;
+ # else /* ACE_SIZEOF_INT != 8 */
+ // Applications will probably have trouble with this.
+ char f[8];
+ # endif /* ACE_SIZEOF_INT != 8 */
+ };
+ # endif /* ACE_SIZEOF_DOUBLE != 8 */
+
+ // 94-9-32 Appendix A defines a 128 bit floating point "long
+ // double" data type, with greatly extended precision and four
+ // more bits of exponent (compared to "double"). This is an IDL
+ // extension, not yet standard.
+
+ # if ACE_SIZEOF_LONG_DOUBLE == 16
+ typedef long double LongDouble;
+ #define ACE_CDR_LONG_DOUBLE_INITIALIZER 0
+ # else
+ # define NONNATIVE_LONGDOUBLE
+ # define ACE_CDR_LONG_DOUBLE_INITIALIZER {{0}}
+ struct ACE_Export LongDouble
+ {
+ char ld[16];
+ int operator== (const LongDouble &rhs) const;
+ int operator!= (const LongDouble &rhs) const;
+ // @@ also need other comparison operators.
+ };
+ # endif /* ACE_SIZEOF_LONG_DOUBLE != 16 */
+
+#if !defined (ACE_CDR_GIOP_MAJOR_VERSION)
+# define ACE_CDR_GIOP_MAJOR_VERSION 1
+#endif /*ACE_CDR_GIOP_MAJOR_VERSION */
+
+#if !defined (ACE_CDR_GIOP_MINOR_VERSION)
+# define ACE_CDR_GIOP_MINOR_VERSION 2
+#endif /* ACE_CDR_GIOP_MINOR_VERSION */
+};
+
+#if defined (__ACE_INLINE__)
+# include "ace/CDR_Base.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include "ace/post.h"
+
+#endif /* ACE_CDR_BASE_H */
diff --git a/ace/Streams/CDR_Base.inl b/ace/Streams/CDR_Base.inl
new file mode 100644
index 00000000000..bf0f8b8d878
--- /dev/null
+++ b/ace/Streams/CDR_Base.inl
@@ -0,0 +1,205 @@
+// -*- C++ -*-
+//
+// $Id$
+
+//
+// The ACE_CDR::swap_X and ACE_CDR::swap_X_array routines are broken
+// in 4 cases for optimization:
+//
+// * x86 Pentium CPU + gnu g++
+// (ACE_HAS_PENTIUM && __GNUG__)
+// => gcc x86 inline assembly.
+//
+// * x86 Pentium CPU and (_MSC_VER) or BORLAND C++)
+// (ACE_HAS_PENTIUM && ( _MSC_VER || __BORLANDC__ )
+// => MSC x86 inline assembly.
+//
+// * 64 bit architecture
+// (ACE_SIZEOF_LONG == 8)
+// => shift/masks using 64bit words.
+//
+// * default
+// (none of the above)
+// => shift/masks using 32bit words.
+//
+//
+// Some things you could find useful to know if you intend to mess
+// with this optimizations for swaps:
+//
+// * MSVC++ don't assume register values are conserved between
+// statements. So you can clobber any register you want,
+// whenever you want (well not *anyone* really, see manual).
+// The MSVC++ optimizer will try to pick different registers
+// for the C++ statements sorrounding your asm block, and if
+// it's not possible will use the stack.
+//
+// * If you clobber registers with asm statements in gcc, you
+// better do it in an asm-only function, or save/restore them
+// before/after in the stack. If not, sorrounding C statements
+// could end using the same registers and big-badda-bum (been
+// there, done that...). The big-badda-bum could happen *even
+// if you specify the clobbered register in your asm's*.
+// Even better, use gcc asm syntax for detecting the register
+// asigned to a certain variable so you don't have to clobber any
+// register directly.
+//
+
+ACE_INLINE void
+ACE_CDR::swap_2 (const char *orig, char* target)
+{
+#if defined(ACE_HAS_PENTIUM)
+# if defined(__GNUG__)
+ unsigned short a =
+ *ACE_reinterpret_cast(const unsigned short*, orig);
+ asm( "rolw $8, %0" : "=r" (a) : "0" (a) );
+ *ACE_reinterpret_cast(unsigned short*, target) = a;
+# elif (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ebx, orig;
+ __asm mov ecx, target;
+ __asm mov ax, [ebx];
+ __asm rol ax, 8;
+ __asm mov [ecx], ax;
+# else
+ // For CISC Platforms this is faster than shift/masks.
+ target[1] = orig[0];
+ target[0] = orig[1];
+# endif
+#else
+ register ACE_UINT16 usrc = * ACE_reinterpret_cast(const ACE_UINT16*, orig);
+ register ACE_UINT16* udst = ACE_reinterpret_cast(ACE_UINT16*, target);
+ *udst = (usrc << 8) | (usrc >> 8);
+#endif /* ACE_HAS_PENTIUM */
+}
+
+ACE_INLINE void
+ACE_CDR::swap_4 (const char* orig, char* target)
+{
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ // We have ACE_HAS_PENTIUM, so we know the sizeof's.
+ register unsigned int j =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ asm ("bswap %1" : "=r" (j) : "0" (j));
+ *ACE_reinterpret_cast(unsigned int*, target) = j;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ebx, orig;
+ __asm mov ecx, target;
+ __asm mov eax, [ebx];
+ __asm bswap eax;
+ __asm mov [ecx], eax;
+#else
+ register ACE_UINT32 x = * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = x;
+#endif
+}
+
+ACE_INLINE void
+ACE_CDR::swap_8 (const char* orig, char* target)
+{
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ register unsigned int i =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ register unsigned int j =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ asm ("bswap %1" : "=r" (i) : "0" (i));
+ asm ("bswap %1" : "=r" (j) : "0" (j));
+ *ACE_reinterpret_cast(unsigned int*, target + 4) = i;
+ *ACE_reinterpret_cast(unsigned int*, target) = j;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ __asm mov 4[edx], eax;
+ __asm mov [edx], ebx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long x =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+ register unsigned long x84 = (x & 0x000000ff000000ffUL) << 24;
+ register unsigned long x73 = (x & 0x0000ff000000ff00UL) << 8;
+ register unsigned long x62 = (x & 0x00ff000000ff0000UL) >> 8;
+ register unsigned long x51 = (x & 0xff000000ff000000UL) >> 24;
+ x = (x84 | x73 | x62 | x51);
+ x = (x << 32) | (x >> 32);
+ *ACE_reinterpret_cast(unsigned long*, target) = x;
+#else
+ register ACE_UINT32 x =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 y =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ y = (y << 24) | ((y & 0xff00) << 8) | ((y & 0xff0000) >> 8) | (y >> 24);
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = y;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = x;
+#endif
+}
+
+ACE_INLINE void
+ACE_CDR::swap_16 (const char* orig, char* target)
+{
+ swap_8 (orig + 8, target);
+ swap_8 (orig, target + 8);
+}
+
+ACE_INLINE void
+ACE_CDR::mb_align (ACE_Message_Block *mb)
+{
+ char *start = ACE_ptr_align_binary (mb->base (),
+ ACE_CDR::MAX_ALIGNMENT);
+ mb->rd_ptr (start);
+ mb->wr_ptr (start);
+}
+
+ACE_INLINE size_t
+ACE_CDR::first_size (size_t minsize)
+{
+ if (minsize == 0)
+ return ACE_CDR::DEFAULT_BUFSIZE;
+
+ size_t newsize = ACE_CDR::DEFAULT_BUFSIZE;
+ while (newsize < minsize)
+ {
+ if (newsize < ACE_CDR::EXP_GROWTH_MAX)
+ {
+ // We grow exponentially at the beginning, this is fast and
+ // reduces the number of allocations.
+ newsize *= 2;
+ }
+ else
+ {
+ // but continuing with exponential growth can result in over
+ // allocations and easily yield an allocation failure.
+ // So we grow linearly when the buffer is too big.
+ newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
+ }
+ }
+ return newsize;
+}
+
+ACE_INLINE size_t
+ACE_CDR::next_size (size_t minsize)
+{
+ size_t newsize =
+ ACE_CDR::first_size (minsize);
+
+ if (newsize == minsize)
+ {
+ // If necessary increment the size
+ if (newsize < ACE_CDR::EXP_GROWTH_MAX)
+ newsize *= 2;
+ else
+ newsize += ACE_CDR::LINEAR_GROWTH_CHUNK;
+ }
+
+ return newsize;
+}
+
+// ****************************************************************
diff --git a/ace/Streams/CDR_Stream.cpp b/ace/Streams/CDR_Stream.cpp
new file mode 100644
index 00000000000..cab64652ea7
--- /dev/null
+++ b/ace/Streams/CDR_Stream.cpp
@@ -0,0 +1,1433 @@
+// $Id$
+
+#include "ace/CDR_Stream.h"
+#include "ace/SString.h"
+
+#if !defined (__ACE_INLINE__)
+# include "ace/CDR_Stream.i"
+#endif /* ! __ACE_INLINE__ */
+
+ACE_RCSID(ace, CDR_Stream, "$Id$")
+
+
+
+// ****************************************************************
+
+ACE_OutputCDR::ACE_OutputCDR (size_t size,
+ int byte_order,
+ ACE_Allocator *buffer_allocator,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator,
+ size_t memcpy_tradeoff,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (size ? size : ACE_CDR::DEFAULT_BUFSIZE + ACE_CDR::MAX_ALIGNMENT,
+ ACE_Message_Block::MB_DATA,
+ 0,
+ 0,
+ buffer_allocator,
+ 0,
+ 0,
+ ACE_Time_Value::zero,
+ ACE_Time_Value::max_time,
+ data_block_allocator,
+ message_block_allocator),
+ current_is_writable_ (1),
+ current_alignment_ (0),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ memcpy_tradeoff_ (memcpy_tradeoff),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+{
+ ACE_CDR::mb_align (&this->start_);
+ this->current_ = &this->start_;
+}
+
+ACE_OutputCDR::ACE_OutputCDR (char *data, size_t size,
+ int byte_order,
+ ACE_Allocator *buffer_allocator,
+ ACE_Allocator *data_block_allocator,
+ ACE_Allocator *message_block_allocator,
+ size_t memcpy_tradeoff,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (size,
+ ACE_Message_Block::MB_DATA,
+ 0,
+ data,
+ buffer_allocator,
+ 0,
+ 0,
+ ACE_Time_Value::zero,
+ ACE_Time_Value::max_time,
+ data_block_allocator,
+ message_block_allocator),
+ current_is_writable_ (1),
+ current_alignment_ (0),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ memcpy_tradeoff_ (memcpy_tradeoff),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+{
+ // We cannot trust the buffer to be properly aligned
+ ACE_CDR::mb_align (&this->start_);
+ this->current_ = &this->start_;
+}
+
+ACE_OutputCDR::ACE_OutputCDR (ACE_Message_Block *data,
+ int byte_order,
+ size_t memcpy_tradeoff,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (data->data_block ()->duplicate ()),
+ current_is_writable_ (1),
+ current_alignment_ (0),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ memcpy_tradeoff_ (memcpy_tradeoff),
+ major_version_ (major_version),
+ minor_version_ (minor_version),
+ char_translator_ (0),
+ wchar_translator_ (0)
+{
+ // We cannot trust the buffer to be properly aligned
+ ACE_CDR::mb_align (&this->start_);
+ this->current_ = &this->start_;
+}
+
+int
+ACE_OutputCDR::grow_and_adjust (size_t size,
+ size_t align,
+ char*& buf)
+{
+ if (!this->current_is_writable_
+ || this->current_->cont () == 0
+ || this->current_->cont ()->size () < size + ACE_CDR::MAX_ALIGNMENT)
+ {
+ // Calculate the new buffer's length; if growing for encode, we
+ // don't grow in "small" chunks because of the cost.
+ size_t cursize = this->current_->size ();
+ if (this->current_->cont () != 0)
+ cursize = this->current_->cont ()->size ();
+
+ size_t minsize = size + ACE_CDR::MAX_ALIGNMENT;
+ // Make sure that there is enough room for <minsize> bytes, but
+ // also make it bigger than whatever our current size is.
+ if (minsize < cursize)
+ {
+ minsize = cursize;
+ }
+
+ size_t newsize =
+ ACE_CDR::next_size (minsize);
+
+ this->good_bit_ = 0;
+ ACE_Message_Block* tmp;
+ ACE_NEW_RETURN (tmp,
+ ACE_Message_Block (newsize,
+ ACE_Message_Block::MB_DATA,
+ 0,
+ 0,
+ this->current_->data_block ()->allocator_strategy (),
+ 0,
+ 0,
+ ACE_Time_Value::zero,
+ ACE_Time_Value::max_time,
+ this->current_->data_block ()->data_block_allocator ()),
+ -1);
+ this->good_bit_ = 1;
+
+ // The new block must start with the same alignment as the
+ // previous block finished.
+ ptr_arith_t tmpalign =
+ ptr_arith_t(tmp->rd_ptr ()) % ACE_CDR::MAX_ALIGNMENT;
+ ptr_arith_t curalign =
+ ptr_arith_t(this->current_alignment_) % ACE_CDR::MAX_ALIGNMENT;
+ int offset = curalign - tmpalign;
+ if (offset < 0)
+ offset += ACE_CDR::MAX_ALIGNMENT;
+ tmp->rd_ptr (offset);
+ tmp->wr_ptr (tmp->rd_ptr ());
+
+ // grow the chain and set the current block.
+ tmp->cont (this->current_->cont ());
+ this->current_->cont (tmp);
+ }
+ this->current_ = this->current_->cont ();
+ this->current_is_writable_ = 1;
+
+ return this->adjust (size, align, buf);
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_wchar (ACE_CDR::WChar x)
+{
+ if (ACE_static_cast (ACE_CDR::Short, major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, minor_version_) == 2)
+ {
+ ACE_CDR::Octet len = ACE_static_cast (ACE_CDR::Octet, sizeof(x));
+ if (this->write_1 (&len))
+ return this->write_octet_array (ACE_reinterpret_cast
+ (const ACE_CDR::Octet*, &x),
+ ACE_static_cast (ACE_CDR::ULong, len));
+ }
+ else
+ if (this->wchar_translator_ == 0)
+ return this->write_2 (ACE_reinterpret_cast (const ACE_CDR::UShort*, &x));
+ return this->wchar_translator_->write_wchar (*this, x);
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_string (ACE_CDR::ULong len,
+ const char *x)
+{
+ // @@ This is a slight violation of "Optimize for the common case",
+ // i.e. normally the translator will be 0, but OTOH the code is
+ // smaller and should be better for the cache ;-) ;-)
+ if (this->char_translator_ != 0)
+ return this->char_translator_->write_string (*this, len, x);
+
+ if (len != 0)
+ {
+ if (this->write_ulong (len + 1))
+ {
+ return this->write_char_array (x, len + 1);
+ }
+ }
+ else
+ {
+ // Be nice to programmers: treat nulls as empty strings not
+ // errors. (OMG-IDL supports languages that don't use the C/C++
+ // notion of null v. empty strings; nulls aren't part of the OMG-IDL
+ // string model.)
+ if (this->write_ulong (1))
+ {
+ return this->write_char (0);
+ }
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_string (const ACE_CString &x)
+{
+ // @@ Leave this method in here, not the `.i' file so that we don't
+ // have to unnecessarily pull in the `ace/SString.h' header.
+ return this->write_string (x.length(), x.c_str());
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_wstring (ACE_CDR::ULong len,
+ const ACE_CDR::WChar *x)
+{
+ // @@ This is a slight violation of "Optimize for the common case",
+ // i.e. normally the translator will be 0, but OTOH the code is
+ // smaller and should be better for the cache ;-) ;-)
+ // What do we do for GIOP 1.2???
+ if (this->wchar_translator_ != 0)
+ return this->wchar_translator_->write_wstring (*this, len, x);
+
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version_) == 2)
+ {
+ if (x != 0)
+ {
+ //In GIOP 1.2 the length field contains the number of bytes
+ //the wstring occupies rather than number of wchars
+ //Taking sizeof might not be a good way! This is a temporary fix.
+ if (this->write_ulong (sizeof(ACE_CDR::WChar)*len))
+ {
+ return this->write_wchar_array (x, len);
+ }
+ }
+ else
+ {
+ //In GIOP 1.2 zero length wstrings are legal
+ return this->write_ulong (0);
+ }
+ }
+
+ else
+ if (x != 0)
+ {
+ if (this->write_ulong (len + 1))
+ return this->write_wchar_array (x, len + 1);
+ }
+ else
+ {
+ if (this->write_ulong (1))
+ return this->write_wchar (0);
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_octet_array_mb (const ACE_Message_Block* mb)
+{
+ // If the buffer is small and it fits in the current message
+ // block it is be cheaper just to copy the buffer.
+ for (const ACE_Message_Block* i = mb;
+ i != 0;
+ i = i->cont ())
+ {
+ size_t length = i->length ();
+
+ // If the mb does not own its data we are forced to make a copy.
+ if (ACE_BIT_ENABLED (i->flags (),
+ ACE_Message_Block::DONT_DELETE))
+ {
+ if (! this->write_array (i->rd_ptr (),
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length))
+ {
+ return 0;
+ }
+ continue;
+ }
+
+ if (length < this->memcpy_tradeoff_
+ && this->current_->wr_ptr () + length < this->current_->end ())
+ {
+ if (! this->write_array (i->rd_ptr (),
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length))
+ {
+ return 0;
+ }
+ continue;
+ }
+
+ ACE_Message_Block* cont;
+ this->good_bit_ = 0;
+ ACE_NEW_RETURN (cont,
+ ACE_Message_Block (i->data_block ()->duplicate ()),
+ 0);
+ this->good_bit_ = 1;
+
+ if (cont != 0)
+ {
+ if (this->current_->cont () != 0)
+ ACE_Message_Block::release (this->current_->cont ());
+ cont->rd_ptr (i->rd_ptr ());
+ cont->wr_ptr (i->wr_ptr ());
+
+ this->current_->cont (cont);
+ this->current_ = cont;
+ this->current_is_writable_ = 0;
+ this->current_alignment_ =
+ (this->current_alignment_ + cont->length ()) % ACE_CDR::MAX_ALIGNMENT;
+ }
+ else
+ {
+ this->good_bit_ = 0;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_1 (const ACE_CDR::Octet *x)
+{
+ char *buf;
+ if (this->adjust (1, buf) == 0)
+ {
+ *ACE_reinterpret_cast(ACE_CDR::Octet*, buf) = *x;
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_2 (const ACE_CDR::UShort *x)
+{
+ char *buf;
+ if (this->adjust (ACE_CDR::SHORT_SIZE, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *ACE_reinterpret_cast(ACE_CDR::UShort*,buf) = *x;
+ return 1;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *ACE_reinterpret_cast (ACE_CDR::UShort *, buf) = *x;
+ return 1;
+ }
+ else
+ {
+ ACE_CDR::swap_2 (ACE_reinterpret_cast (const char*, x), buf);
+ return 1;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_4 (const ACE_CDR::ULong *x)
+{
+ char *buf;
+ if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *ACE_reinterpret_cast(ACE_CDR::ULong*,buf) = *x;
+ return 1;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *ACE_reinterpret_cast (ACE_CDR::ULong *, buf) = *x;
+ return 1;
+ }
+ else
+ {
+ ACE_CDR::swap_4 (ACE_reinterpret_cast (const char*, x), buf);
+ return 1;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_8 (const ACE_CDR::ULongLong *x)
+{
+ char *buf;
+
+ if (this->adjust (ACE_CDR::LONGLONG_SIZE, buf) == 0)
+ {
+#if defined (__arm__)
+ // Convert to Intel format (12345678 => 56781234)
+ const char *orig = ACE_reinterpret_cast (const char *, x);
+ char *target = buf;
+ register ACE_UINT32 x =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig);
+ register ACE_UINT32 y =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig + 4);
+ *ACE_reinterpret_cast (ACE_UINT32 *, target) = y;
+ *ACE_reinterpret_cast (ACE_UINT32 *, target + 4) = x;
+ return 1;
+#else
+# if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *ACE_reinterpret_cast (ACE_CDR::ULongLong *,buf) = *x;
+ return 1;
+# else
+ if (!this->do_byte_swap_)
+ {
+ *ACE_reinterpret_cast (ACE_CDR::ULongLong *, buf) = *x;
+ return 1;
+ }
+ else
+ {
+ ACE_CDR::swap_8 (ACE_reinterpret_cast (const char*, x), buf);
+ return 1;
+ }
+# endif /* ACE_ENABLE_SWAP_ON_WRITE */
+#endif /* !__arm__ */
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_16 (const ACE_CDR::LongDouble *x)
+{
+ char* buf;
+ if (this->adjust (ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ *ACE_reinterpret_cast(ACE_CDR::LongDouble*,buf) = *x;
+ return 1;
+#else
+ if (!this->do_byte_swap_)
+ {
+ *ACE_reinterpret_cast (ACE_CDR::LongDouble *, buf) = *x;
+ return 1;
+ }
+ else
+ {
+ ACE_CDR::swap_16 (ACE_reinterpret_cast (const char*, x), buf);
+ return 1;
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_array (const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return 1;
+ char *buf;
+ if (this->adjust (size * length, align, buf) == 0)
+ {
+#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
+ ACE_OS::memcpy (buf, x, size*length);
+ return 1;
+#else
+ if (!this->do_byte_swap_ || size == 1)
+ {
+ ACE_OS::memcpy (buf, x, size*length);
+ return 1;
+ }
+ else
+ {
+ const char *source = ACE_reinterpret_cast (const char *, x);
+ switch (size)
+ {
+ case 2:
+ ACE_CDR::swap_2_array (source, buf, length);
+ return 1;
+ case 4:
+ ACE_CDR::swap_4_array (source, buf, length);
+ return 1;
+ case 8:
+ ACE_CDR::swap_8_array (source, buf, length);
+ return 1;
+ case 16:
+ ACE_CDR::swap_16_array (source, buf, length);
+ return 1;
+ default:
+ // TODO: print something?
+ this->good_bit_ = 0;
+ return 0;
+ }
+ }
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ }
+ this->good_bit_ = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_OutputCDR::write_boolean_array (const ACE_CDR::Boolean* x,
+ ACE_CDR::ULong length)
+{
+ // It is hard to optimize this, the spec requires that on the wire
+ // booleans be represented as a byte with value 0 or 1, but in
+ // memoery it is possible (though very unlikely) that a boolean has
+ // a non-zero value (different from 1).
+ // We resort to a simple loop.
+ const ACE_CDR::Boolean* end = x + length;
+ for (const ACE_CDR::Boolean* i = x; i != end && this->good_bit (); ++i)
+ {
+ this->write_boolean (*i);
+ }
+ return this->good_bit ();
+}
+
+// ****************************************************************
+
+ACE_InputCDR::ACE_InputCDR (const char *buf,
+ size_t bufsiz,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (buf, bufsiz),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+ this->start_.wr_ptr (bufsiz);
+}
+
+ACE_InputCDR::ACE_InputCDR (size_t bufsiz,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (bufsiz),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_Message_Block *data,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+ this->reset (data, byte_order);
+}
+
+ACE_InputCDR::ACE_InputCDR (ACE_Data_Block *data,
+ ACE_Message_Block::Message_Flags flag,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (data, flag),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+}
+
+ACE_InputCDR::ACE_InputCDR (ACE_Data_Block *data,
+ ACE_Message_Block::Message_Flags flag,
+ size_t rd_pos,
+ size_t wr_pos,
+ int byte_order,
+ ACE_CDR::Octet major_version,
+ ACE_CDR::Octet minor_version)
+ : start_ (data, flag),
+ do_byte_swap_ (byte_order != ACE_CDR_BYTE_ORDER),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (major_version),
+ minor_version_ (minor_version)
+{
+ // Set the read pointer
+ this->start_.rd_ptr (rd_pos);
+
+ // Set the write pointer after doing a sanity check.
+ char* wrpos = this->start_.base () + wr_pos;
+
+ if (this->start_.end () >= wrpos)
+ {
+ this->start_.wr_ptr (wr_pos);
+ }
+}
+
+
+ACE_InputCDR::ACE_InputCDR (const ACE_InputCDR& rhs,
+ size_t size,
+ ACE_CDR::Long offset)
+ : start_ (rhs.start_,
+ ACE_CDR::MAX_ALIGNMENT),
+ do_byte_swap_ (rhs.do_byte_swap_),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_)
+{
+ // Align the base pointer assuming that the incoming stream is also
+ // aligned the way we are aligned
+ char *incoming_start = ACE_ptr_align_binary (rhs.start_.base (),
+ ACE_CDR::MAX_ALIGNMENT);
+
+ size_t newpos =
+ (rhs.start_.rd_ptr() - incoming_start) + offset;
+
+ if (newpos <= this->start_.space ()
+ && newpos + size <= this->start_.space ())
+ {
+ this->start_.rd_ptr (newpos);
+ this->start_.wr_ptr (newpos + size);
+ }
+ else
+ {
+ this->good_bit_ = 0;
+ }
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_InputCDR& rhs,
+ size_t size)
+ : start_ (rhs.start_,
+ ACE_CDR::MAX_ALIGNMENT),
+ do_byte_swap_ (rhs.do_byte_swap_),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_)
+{
+ // Align the base pointer assuming that the incoming stream is also
+ // aligned the way we are aligned
+ char *incoming_start = ACE_ptr_align_binary (rhs.start_.base (),
+ ACE_CDR::MAX_ALIGNMENT);
+
+ size_t newpos =
+ rhs.start_.rd_ptr() - incoming_start;
+
+ if (newpos <= this->start_.space ()
+ && newpos + size <= this->start_.space ())
+ {
+ // Notice that ACE_Message_Block::duplicate may leave the
+ // wr_ptr() with a higher value that what we actually want.
+ this->start_.rd_ptr (newpos);
+ this->start_.wr_ptr (newpos + size);
+
+ ACE_CDR::Octet byte_order;
+ this->read_octet (byte_order);
+ this->do_byte_swap_ = (byte_order != ACE_CDR_BYTE_ORDER);
+ }
+ else
+ {
+ this->good_bit_ = 0;
+ }
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_InputCDR& rhs)
+ : start_ (rhs.start_,
+ ACE_CDR::MAX_ALIGNMENT),
+ do_byte_swap_ (rhs.do_byte_swap_),
+ good_bit_ (1),
+ char_translator_ (rhs.char_translator_),
+ wchar_translator_ (rhs.wchar_translator_),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_)
+{
+ char *buf = ACE_ptr_align_binary (rhs.start_.base (),
+ ACE_CDR::MAX_ALIGNMENT);
+
+ size_t rd_offset = rhs.start_.rd_ptr () - buf;
+ size_t wr_offset = rhs.start_.wr_ptr () - buf;
+ this->start_.rd_ptr (rd_offset);
+ this->start_.wr_ptr (wr_offset);
+}
+
+ACE_InputCDR::ACE_InputCDR (ACE_InputCDR::Transfer_Contents x)
+ : start_ (x.rhs_.start_.data_block ()),
+ do_byte_swap_ (x.rhs_.do_byte_swap_),
+ good_bit_ (1),
+ char_translator_ (x.rhs_.char_translator_),
+ wchar_translator_ (x.rhs_.wchar_translator_),
+ major_version_ (x.rhs_.major_version_),
+ minor_version_ (x.rhs_.minor_version_)
+{
+ this->start_.rd_ptr (x.rhs_.start_.rd_ptr ());
+ this->start_.wr_ptr (x.rhs_.start_.wr_ptr ());
+
+ ACE_Data_Block* db = this->start_.data_block ()->clone_nocopy ();
+ (void) x.rhs_.start_.replace_data_block (db);
+}
+
+ACE_InputCDR&
+ACE_InputCDR::operator= (const ACE_InputCDR& rhs)
+{
+ if (this != &rhs)
+ {
+ this->start_.data_block (rhs.start_.data_block ()->duplicate ());
+ this->start_.rd_ptr (rhs.start_.rd_ptr ());
+ this->start_.wr_ptr (rhs.start_.wr_ptr ());
+ this->do_byte_swap_ = rhs.do_byte_swap_;
+ this->good_bit_ = 1;
+ this->major_version_ = rhs.major_version_;
+ this->minor_version_ = rhs.minor_version_;
+ }
+ return *this;
+}
+
+ACE_InputCDR::ACE_InputCDR (const ACE_OutputCDR& rhs,
+ ACE_Allocator* buffer_allocator,
+ ACE_Allocator* data_block_allocator,
+ ACE_Allocator* message_block_allocator)
+ : start_ (rhs.total_length () + ACE_CDR::MAX_ALIGNMENT,
+ ACE_Message_Block::MB_DATA,
+ 0,
+ 0,
+ buffer_allocator,
+ 0,
+ 0,
+ ACE_Time_Value::zero,
+ ACE_Time_Value::max_time,
+ data_block_allocator,
+ message_block_allocator),
+ do_byte_swap_ (rhs.do_byte_swap_),
+ good_bit_ (1),
+ char_translator_ (0),
+ wchar_translator_ (0),
+ major_version_ (rhs.major_version_),
+ minor_version_ (rhs.minor_version_)
+{
+ ACE_CDR::mb_align (&this->start_);
+ for (const ACE_Message_Block *i = rhs.begin ();
+ i != rhs.end ();
+ i = i->cont ())
+ this->start_.copy (i->rd_ptr (), i->length ());
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_wchar (void)
+{
+ if (ACE_static_cast (ACE_CDR::Short, major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, minor_version_) == 2)
+ {
+ ACE_CDR::Octet len;
+ if (this->read_1 (&len))
+ return this->skip_bytes (ACE_static_cast (size_t, len));
+ }
+ else
+ {
+ ACE_CDR::WChar x;
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*,&x));
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_wchar (ACE_CDR::WChar& x)
+{
+ if (ACE_static_cast (ACE_CDR::Short, major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, minor_version_) == 2)
+ {
+ ACE_CDR::Octet len;
+
+ if (this->read_1 (&len))
+ {
+ return this->read_octet_array (
+ ACE_reinterpret_cast (ACE_CDR::Octet*,
+ &x),
+ ACE_static_cast (ACE_CDR::ULong,
+ len)
+ );
+ }
+ }
+ else if (this->wchar_translator_ == 0)
+ {
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*,
+ &x));
+ }
+
+ return this->wchar_translator_->read_wchar (*this,
+ x);
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_string (char *&x)
+{
+ // @@ This is a slight violation of "Optimize for the common case",
+ // i.e. normally the translator will be 0, but OTOH the code is
+ // smaller and should be better for the cache ;-) ;-)
+ if (this->char_translator_ != 0)
+ {
+ return this->char_translator_->read_string (*this,
+ x);
+ }
+
+ ACE_CDR::ULong len;
+
+ this->read_ulong (len);
+ // A check for the length being too great is done later in the
+ // call to read_char_array but we want to have it done before
+ // the memory is allocated.
+ if (len > 0 && len <= this->length())
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::Char[len],
+ 0);
+ if (this->read_char_array (x, len))
+ {
+ return 1;
+ }
+
+ delete [] x;
+ }
+ else if (len == 0)
+ {
+ // Convert any null strings to empty strings since empty
+ // strings can cause crashes. (See bug 58.)
+ ACE_NEW_RETURN (x,
+ ACE_CDR::Char[1],
+ 0);
+ ACE_OS::strcpy (ACE_const_cast (char *&, x), "");
+ return 1;
+ }
+
+ x = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_string (ACE_CString &x)
+{
+ ACE_CDR::Char *data;
+ if (this->read_string (data))
+ {
+ x = data;
+ delete [] data;
+ return 1;
+ }
+
+ x = "";
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_wstring (ACE_CDR::WChar*& x)
+{
+ // @@ This is a slight violation of "Optimize for the common case",
+ // i.e. normally the translator will be 0, but OTOH the code is
+ // smaller and should be better for the cache ;-) ;-)
+ if (this->wchar_translator_ != 0)
+ return this->wchar_translator_->read_wstring (*this, x);
+
+ ACE_CDR::ULong len;
+ this->read_ulong (len);
+
+ // A check for the length being too great is done later in the
+ // call to read_char_array but we want to have it done before
+ // the memory is allocated.
+ if (len > 0 && len <= this->length())
+ {
+
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version_) == 2)
+ {
+ len = len / sizeof (ACE_CDR::WChar);
+
+ //allocating one extra for the null character needed by applications
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len + 1],
+ 0);
+
+ if (this->read_wchar_array (x, len))
+ {
+
+ //Null character used by applications to find the end of
+ //the wstring
+ //Is this okay with the GIOP 1.2 spec??
+ x[len] = '\x00';
+
+ return 1;
+ }
+ }
+ else
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len],
+ 0);
+
+ if (this->read_wchar_array (x, len))
+ return 1;
+ }
+
+ delete [] x;
+ }
+ else if (len == 0)
+ {
+ // Convert any null strings to empty strings since empty
+ // strings can cause crashes. (See bug 58.)
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar[1],
+ 0);
+ ACE_OS::memcpy(x, "", 2);
+ return 1;
+ }
+
+ this->good_bit_ = 0;
+ x = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_array (void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return 1;
+ char* buf;
+
+ if (this->adjust (size * length, align, buf) == 0)
+ {
+#if defined (ACE_DISABLE_SWAP_ON_READ)
+ ACE_OS::memcpy (x, buf, size*length);
+#else
+ if (!this->do_byte_swap_ || size == 1)
+ {
+ ACE_OS::memcpy (x, buf, size*length);
+ }
+ else
+ {
+ char *target = ACE_reinterpret_cast (char*, x);
+ switch (size)
+ {
+ case 2:
+ ACE_CDR::swap_2_array (buf, target, length);
+ break;
+ case 4:
+ ACE_CDR::swap_4_array (buf, target, length);
+ break;
+ case 8:
+ ACE_CDR::swap_8_array (buf, target, length);
+ break;
+ case 16:
+ ACE_CDR::swap_16_array (buf, target, length);
+ break;
+ default:
+ // TODO: print something?
+ this->good_bit_ = 0;
+ return 0;
+ }
+ }
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return this->good_bit_;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_boolean_array (ACE_CDR::Boolean *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ // It is hard to optimize this, the spec requires that on the wire
+ // booleans be represented as a byte with value 0 or 1, but in
+ // memoery it is possible (though very unlikely) that a boolean has
+ // a non-zero value (different from 1).
+ // We resort to a simple loop.
+ for (ACE_CDR::ULong i = 0; i != length && this->good_bit_; ++i)
+ {
+ this->read_boolean (x[i]);
+ }
+ return this->good_bit_;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_1 (ACE_CDR::Octet *x)
+{
+ if (this->rd_ptr () < this->wr_ptr ())
+ {
+ *x = *ACE_reinterpret_cast (ACE_CDR::Octet*,this->rd_ptr ());
+ this->start_.rd_ptr (1);
+ return 1;
+ }
+
+ this->good_bit_ = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_2 (ACE_CDR::UShort *x)
+{
+ char *buf;
+ if (this->adjust (ACE_CDR::SHORT_SIZE, buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ {
+ *x = *ACE_reinterpret_cast (ACE_CDR::UShort*, buf);
+ }
+ else
+ {
+ ACE_CDR::swap_2 (buf, ACE_reinterpret_cast (char*, x));
+ }
+#else
+ *x = *ACE_reinterpret_cast(ACE_CDR::UShort*,buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_4 (ACE_CDR::ULong *x)
+{
+ char *buf;
+ if (this->adjust (ACE_CDR::LONG_SIZE, buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ {
+ *x = *ACE_reinterpret_cast (ACE_CDR::ULong*, buf);
+ }
+ else
+ {
+ ACE_CDR::swap_4 (buf, ACE_reinterpret_cast (char*, x));
+ }
+#else
+ *x = *ACE_reinterpret_cast(ACE_CDR::ULong*,buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_8 (ACE_CDR::ULongLong *x)
+{
+ char *buf;
+
+ if (this->adjust (ACE_CDR::LONGLONG_SIZE, buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+# if defined (__arm__)
+ if (!this->do_byte_swap_)
+ {
+ // Convert from Intel format (12345678 => 56781234)
+ const char *orig = buf;
+ char *target = ACE_reinterpret_cast (char *, x);
+ register ACE_UINT32 x =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig);
+ register ACE_UINT32 y =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig + 4);
+ *ACE_reinterpret_cast (ACE_UINT32 *, target) = y;
+ *ACE_reinterpret_cast (ACE_UINT32 *, target + 4) = x;
+ }
+ else
+ {
+ // Convert from Sparc format (12345678 => 43218765)
+ const char *orig = buf;
+ char *target = ACE_reinterpret_cast (char *, x);
+ register ACE_UINT32 x =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig);
+ register ACE_UINT32 y =
+ *ACE_reinterpret_cast (const ACE_UINT32 *, orig + 4);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ y = (y << 24) | ((y & 0xff00) << 8) | ((y & 0xff0000) >> 8) | (y >> 24);
+ *ACE_reinterpret_cast (ACE_UINT32 *, target) = x;
+ *ACE_reinterpret_cast (ACE_UINT32 *, target + 4) = y;
+ }
+# else
+ if (!this->do_byte_swap_)
+ {
+ *x = *ACE_reinterpret_cast (ACE_CDR::ULongLong *, buf);
+ }
+ else
+ {
+ ACE_CDR::swap_8 (buf, ACE_reinterpret_cast (char *, x));
+ }
+# endif /* !__arm__ */
+#else
+ *x = *ACE_reinterpret_cast (ACE_CDR::ULongLong *, buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return 1;
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_16 (ACE_CDR::LongDouble *x)
+{
+ char *buf;
+ if (this->adjust (ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ buf) == 0)
+ {
+#if !defined (ACE_DISABLE_SWAP_ON_READ)
+ if (!this->do_byte_swap_)
+ {
+ *x = *ACE_reinterpret_cast (ACE_CDR::LongDouble *, buf);
+ }
+ else
+ {
+ ACE_CDR::swap_16 (buf, ACE_reinterpret_cast (char*, x));
+ }
+#else
+ *x = *ACE_reinterpret_cast(ACE_CDR::LongDouble*,buf);
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_string (void)
+{
+ ACE_CDR::ULong len;
+ if (this->read_ulong (len))
+ {
+ if (this->rd_ptr () + len <= this->wr_ptr ())
+ {
+ this->rd_ptr (len);
+ return 1;
+ }
+ this->good_bit_ = 0;
+ }
+
+ return 0;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_wstring (void)
+{
+ ACE_CDR::Boolean continue_skipping = 1;
+ ACE_CDR::ULong len;
+
+ continue_skipping = read_ulong (len);
+
+ if (continue_skipping != 0 && len != 0)
+ {
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version_) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version_) == 2)
+ continue_skipping = this->skip_bytes ((size_t)len);
+ else
+ while (continue_skipping != 0 && len--)
+ continue_skipping = this->skip_wchar ();
+ }
+ return continue_skipping;
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::skip_bytes (size_t len)
+{
+ if (this->rd_ptr () + len <= this->wr_ptr ())
+ {
+ this->rd_ptr (len);
+ return 1;
+ }
+ this->good_bit_ = 0;
+ return 0;
+}
+
+int
+ACE_InputCDR::grow (size_t newsize)
+{
+ if (ACE_CDR::grow (&this->start_, newsize) == -1)
+ return -1;
+
+ ACE_CDR::mb_align (&this->start_);
+ this->start_.wr_ptr (newsize);
+ return 0;
+}
+
+void
+ACE_InputCDR::reset (const ACE_Message_Block* data,
+ int byte_order)
+{
+ this->reset_byte_order (byte_order);
+ ACE_CDR::consolidate (&this->start_, data);
+}
+
+void
+ACE_InputCDR::steal_from (ACE_InputCDR &cdr)
+{
+ this->do_byte_swap_ = cdr.do_byte_swap_;
+ this->start_.data_block (cdr.start_.data_block ()->duplicate ());
+
+ // If the message block had a DONT_DELETE flags, just clear it off..
+ this->start_.clr_self_flags (ACE_Message_Block::DONT_DELETE);
+ this->start_.rd_ptr (cdr.start_.rd_ptr ());
+
+ this->start_.wr_ptr (cdr.start_.wr_ptr ());
+ this->major_version_ = cdr.major_version_;
+ this->minor_version_ = cdr.minor_version_;
+ cdr.reset_contents ();
+}
+
+void
+ACE_InputCDR::exchange_data_blocks (ACE_InputCDR &cdr)
+{
+ // Exchange byte orders
+ int byte_order = cdr.do_byte_swap_;
+ cdr.do_byte_swap_ = this->do_byte_swap_;
+ this->do_byte_swap_ = byte_order;
+
+ // Get the destination read and write pointers
+ size_t drd_pos =
+ cdr.start_.rd_ptr () - cdr.start_.base ();
+ size_t dwr_pos =
+ cdr.start_.wr_ptr () - cdr.start_.base ();
+
+ // Get the source read & write pointers
+ size_t srd_pos =
+ this->start_.rd_ptr () - this->start_.base ();
+ size_t swr_pos =
+ this->start_.wr_ptr () - this->start_.base ();
+
+ // Exchange data_blocks. Dont release any of the data blocks.
+ ACE_Data_Block *dnb =
+ this->start_.replace_data_block (cdr.start_.data_block ());
+ cdr.start_.replace_data_block (dnb);
+
+ // Exchange the flags information..
+ ACE_Message_Block::Message_Flags df = cdr.start_.self_flags ();
+ ACE_Message_Block::Message_Flags sf = this->start_.self_flags ();
+
+ cdr.start_.clr_self_flags (df);
+ this->start_.clr_self_flags (sf);
+
+ cdr.start_.set_self_flags (sf);
+ this->start_.set_self_flags (df);
+
+ // Reset the <cdr> pointers to zero before it is set again.
+ cdr.start_.reset ();
+ this->start_.reset ();
+
+ // Set the read and write pointers.
+ if (cdr.start_.size () >= srd_pos)
+ cdr.start_.rd_ptr (srd_pos);
+
+ if (cdr.start_.size () >= swr_pos)
+ cdr.start_.wr_ptr (swr_pos);
+
+ if (this->start_.size () >= drd_pos)
+ this->start_.rd_ptr (drd_pos);
+
+ if (this->start_.size () >= dwr_pos)
+ this->start_.wr_ptr (dwr_pos);
+
+ ACE_CDR::Octet dmajor = cdr.major_version_;
+ ACE_CDR::Octet dminor = cdr.minor_version_;
+
+ // Exchange the GIOP version info
+ cdr.major_version_ = this->major_version_;
+ cdr.minor_version_ = this->minor_version_;
+
+ this->major_version_ = dmajor;
+ this->minor_version_ = dminor;
+}
+
+
+ACE_Data_Block *
+ACE_InputCDR::clone_from (ACE_InputCDR &cdr)
+{
+ this->do_byte_swap_ = cdr.do_byte_swap_;
+
+ // Replace our data block by using the incoming CDR stream.
+ ACE_Data_Block *db =
+ this->start_.replace_data_block (cdr.start_.data_block ()->clone_nocopy ());
+
+ // Align the start_ message block.
+ ACE_CDR::mb_align (&this->start_);
+
+ // Clear the DONT_DELETE flag if it has been set
+ this->start_.clr_self_flags (ACE_Message_Block::DONT_DELETE);
+
+ // Get the read & write pointer positions in the incoming CDR
+ // streams
+ char *rd_ptr = cdr.start_.rd_ptr ();
+ char *wr_ptr = cdr.start_.wr_ptr ();
+
+ // Now reset the incoming CDR stream
+ cdr.start_.reset ();
+
+ // As we have reset the stream, try to align the underlying message
+ // block in the incoming stream
+ ACE_CDR::mb_align (&cdr.start_);
+
+ // Get the read & write pointer positions again
+ char *nrd_ptr = cdr.start_.rd_ptr ();
+ char *nwr_ptr = cdr.start_.wr_ptr ();
+
+ // Actual length of the stream is..
+ // @todo: This will look idiotic, but we dont seem to have much of a
+ // choice. How do we calculate the length of the incoming stream?
+ // Calling the method before calling reset () would give us the
+ // wrong length of the stream that needs copying. So we do the
+ // calulation like this
+ // (1) We get the <rd_ptr> and <wr_ptr> positions of the incoming
+ // stream.
+ // (2) Then we reset the <incoming> stream and then align it.
+ // (3) We get the <rd_ptr> and <wr_ptr> positions again. (Points #1
+ // thru #3 has been done already)
+ // (4) The difference in the <rd_ptr> and <wr_ptr> positions gives
+ // us the following, the actual bytes traversed by the <rd_ptr> and
+ // <wr_ptr>.
+ // (5) The bytes traversed by the <wr_ptr> is the actual length of
+ // the stream.
+
+ // Actual bytes traversed
+ size_t rd_bytes = rd_ptr - nrd_ptr;
+ size_t wr_bytes = wr_ptr - nwr_ptr;
+
+ // Now do the copy
+ (void) ACE_OS::memcpy (this->start_.wr_ptr (),
+ cdr.start_.rd_ptr (),
+ wr_bytes);
+
+ // Set the read pointer position to the same point as that was in
+ // <incoming> cdr.
+ this->start_.rd_ptr (rd_bytes);
+ this->start_.wr_ptr (wr_bytes);
+
+ // We have changed the read & write pointers for the incoming
+ // stream. Set them back to the positions that they were before..
+ cdr.start_.rd_ptr (rd_bytes);
+ cdr.start_.wr_ptr (wr_bytes);
+
+ this->major_version_ = cdr.major_version_;
+ this->minor_version_ = cdr.minor_version_;
+
+ return db;
+}
+
+ACE_Message_Block*
+ACE_InputCDR::steal_contents (void)
+{
+ ACE_Message_Block* block =
+ this->start_.clone ();
+ this->start_.data_block (block->data_block ()->clone ());
+
+ // If at all our message had a DONT_DELETE flag set, just clear it
+ // off.
+ this->start_.clr_self_flags (ACE_Message_Block::DONT_DELETE);
+
+ ACE_CDR::mb_align (&this->start_);
+
+ return block;
+}
+
+void
+ACE_InputCDR::reset_contents (void)
+{
+ this->start_.data_block (this->start_.data_block ()->clone_nocopy
+ ());
+
+ // Reset the flags...
+ this->start_.clr_self_flags (ACE_Message_Block::DONT_DELETE);
+}
+
+// --------------------------------------------------------------
+
+#if defined (VXWORKS) && defined (ghs)
+ACE_CDR::Boolean
+ACE_OutputCDR::write_float (ACE_CDR::Float x)
+{
+ return this->write_4 (ACE_reinterpret_cast (const ACE_CDR::ULong*, &x));
+}
+
+ACE_CDR::Boolean
+ACE_InputCDR::read_float (ACE_CDR::Float &x)
+{
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*, &x));
+}
+#endif /* VXWORKS && ghs */
+
+ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, const ACE_CString &x)
+{
+ os.write_string (x);
+ return os.good_bit ();
+}
+
+
+ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CString &x)
+{
+ is.read_string (x);
+ return is.good_bit ();
+}
diff --git a/ace/Streams/CDR_Stream.h b/ace/Streams/CDR_Stream.h
new file mode 100644
index 00000000000..8b1ac7e9c0f
--- /dev/null
+++ b/ace/Streams/CDR_Stream.h
@@ -0,0 +1,1143 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file CDR_Stream.h
+ *
+ * $Id$
+ *
+ * ACE Common Data Representation (CDR) marshaling and demarshaling
+ * classes.
+ *
+ * This implementation was inspired in the CDR class in SunSoft's
+ * IIOP engine, but has a completely different implementation and a
+ * different interface too.
+ *
+ * The current implementation assumes that the host has 1-byte,
+ * 2-byte and 4-byte integral types, and that it has single
+ * precision and double precision IEEE floats.
+ * Those assumptions are pretty good these days, with Crays beign
+ * the only known exception.
+ *
+ * @author TAO version by
+ * @author Aniruddha Gokhale <gokhale@cs.wustl.edu>
+ * @author Carlos O'Ryan<coryan@cs.wustl.edu>
+ * @author ACE version by
+ * @author Jeff Parsons <parsons@cs.wustl.edu>
+ * @author Istvan Buki <istvan.buki@euronet.be>
+ * @author Codeset translation by
+ * @author Jim Rogers <jrogers@viasoft.com>
+ */
+//=============================================================================
+
+#ifndef ACE_CDR_STREAM_H
+#define ACE_CDR_STREAM_H
+
+#include "ace/pre.h"
+
+#include "ace/CDR_Base.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Message_Block.h"
+
+class ACE_Char_Codeset_Translator;
+class ACE_WChar_Codeset_Translator;
+
+class ACE_InputCDR;
+
+/**
+ * @class ACE_OutputCDR
+ *
+ * @brief A CDR stream for writing, i.e. for marshalling.
+ *
+ * This class is based on the the CORBA spec for Java (98-02-29),
+ * java class omg.org.CORBA.portable.OutputStream. It diverts in
+ * a few ways:
+ * + Operations taking arrays don't have offsets, because in C++
+ * it is easier to describe an array starting from x+offset.
+ * + Operations return an error status, because exceptions are
+ * not widely available in C++ (yet).
+ */
+class ACE_Export ACE_OutputCDR
+{
+public:
+ /**
+ * The Codeset translators need access to some private members to
+ * efficiently marshal arrays
+ * For reading from an output CDR stream.
+ */
+ friend class ACE_Char_Codeset_Translator;
+ friend class ACE_WChar_Codeset_Translator;
+ friend class ACE_InputCDR;
+
+ /// Default constructor, allocates <size> bytes in the internal
+ /// buffer, if <size> == 0 it allocates the default size.
+ ACE_OutputCDR (size_t size = 0,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_Allocator* buffer_allocator = 0,
+ ACE_Allocator* data_block_allocator = 0,
+ ACE_Allocator* message_block_allocator = 0,
+ size_t memcpy_tradeoff =
+ ACE_DEFAULT_CDR_MEMCPY_TRADEOFF,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Build a CDR stream with an initial buffer, it will *not* remove
+ /// <data>, since it did not allocated it. It's important to be careful
+ /// with the alignment of <data>.
+ /**
+ * Create an output stream from an arbitrary buffer, care must be
+ * exercised with alignment, because this contructor will align if
+ * needed. In this case <data> will not point to the start off the
+ * output stream. begin()->rd_prt() points to the start off the
+ * output stream. See ACE_ptr_align_binary() to properly align a
+ * pointer and use ACE_CDR::MAX_ALIGNMENT for the correct alignment.
+ */
+ ACE_OutputCDR (char *data,
+ size_t size,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_Allocator* buffer_allocator = 0,
+ ACE_Allocator* data_block_allocator = 0,
+ ACE_Allocator* message_block_allocator = 0,
+ size_t memcpy_tradeoff=
+ ACE_DEFAULT_CDR_MEMCPY_TRADEOFF,
+ ACE_CDR::Octet giop_major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet giop_minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Build a CDR stream with an initial Message_Block chain, it will
+ /// *not* remove <data>, since it did not allocate it.
+ ACE_OutputCDR (ACE_Message_Block *data,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ size_t memcpy_tradeoff=
+ ACE_DEFAULT_CDR_MEMCPY_TRADEOFF,
+ ACE_CDR::Octet giop_major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet giop_minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// destructor
+ ~ACE_OutputCDR (void);
+
+ /**
+ * Disambiguate overload when inserting booleans, octets, chars, and
+ * bounded strings.
+ */
+ //@{ @name Helper classes
+
+ struct ACE_Export from_boolean
+ {
+ from_boolean (ACE_CDR::Boolean b);
+ ACE_CDR::Boolean val_;
+ };
+
+ struct ACE_Export from_octet
+ {
+ from_octet (ACE_CDR::Octet o);
+ ACE_CDR::Octet val_;
+ };
+
+ struct ACE_Export from_char
+ {
+ from_char (ACE_CDR::Char c);
+ ACE_CDR::Char val_;
+ };
+
+ struct ACE_Export from_wchar
+ {
+ from_wchar (ACE_CDR::WChar wc);
+ ACE_CDR::WChar val_;
+ };
+
+ struct ACE_Export from_string
+ {
+ from_string (ACE_CDR::Char* s,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy = 0);
+ from_string (const ACE_CDR::Char* s,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy = 0);
+ ACE_CDR::Char *val_;
+ ACE_CDR::ULong bound_;
+ ACE_CDR::Boolean nocopy_;
+ };
+
+ struct ACE_Export from_wstring
+ {
+ from_wstring (ACE_CDR::WChar* ws,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy = 0);
+ from_wstring (const ACE_CDR::WChar* ws,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy = 0);
+ ACE_CDR::WChar *val_;
+ ACE_CDR::ULong bound_;
+ ACE_CDR::Boolean nocopy_;
+ };
+ //@}
+
+ // Return 0 on failure and 1 on success.
+ //@{ @name Write operations
+ ACE_CDR::Boolean write_boolean (ACE_CDR::Boolean x);
+ ACE_CDR::Boolean write_char (ACE_CDR::Char x);
+ ACE_CDR::Boolean write_wchar (ACE_CDR::WChar x);
+ ACE_CDR::Boolean write_octet (ACE_CDR::Octet x);
+ ACE_CDR::Boolean write_short (ACE_CDR::Short x);
+ ACE_CDR::Boolean write_ushort (ACE_CDR::UShort x);
+ ACE_CDR::Boolean write_long (ACE_CDR::Long x);
+ ACE_CDR::Boolean write_ulong (ACE_CDR::ULong x);
+ ACE_CDR::Boolean write_longlong (const ACE_CDR::LongLong &x);
+ ACE_CDR::Boolean write_ulonglong (const ACE_CDR::ULongLong &x);
+ ACE_CDR::Boolean write_float (ACE_CDR::Float x);
+ ACE_CDR::Boolean write_double (const ACE_CDR::Double &x);
+ ACE_CDR::Boolean write_longdouble (const ACE_CDR::LongDouble &x);
+
+ /// For string we offer methods that accept a precomputed length.
+ ACE_CDR::Boolean write_string (const ACE_CDR::Char *x);
+ ACE_CDR::Boolean write_string (ACE_CDR::ULong len,
+ const ACE_CDR::Char *x);
+ ACE_CDR::Boolean write_string (const ACE_CString &x);
+ ACE_CDR::Boolean write_wstring (const ACE_CDR::WChar *x);
+ ACE_CDR::Boolean write_wstring (ACE_CDR::ULong length,
+ const ACE_CDR::WChar *x);
+ //@}
+
+ /// Note: the portion written starts at <x> and ends
+ /// at <x + length>.
+ /// The length is *NOT* stored into the CDR stream.
+ //@{ @name Array write operations
+ ACE_CDR::Boolean write_boolean_array (const ACE_CDR::Boolean *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_char_array (const ACE_CDR::Char *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_wchar_array (const ACE_CDR::WChar* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_octet_array (const ACE_CDR::Octet* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_short_array (const ACE_CDR::Short *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_ushort_array (const ACE_CDR::UShort *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_long_array (const ACE_CDR::Long *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_ulong_array (const ACE_CDR::ULong *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_longlong_array (const ACE_CDR::LongLong* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_ulonglong_array (const ACE_CDR::ULongLong *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_float_array (const ACE_CDR::Float *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_double_array (const ACE_CDR::Double *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean write_longdouble_array (const ACE_CDR::LongDouble* x,
+ ACE_CDR::ULong length);
+
+ /// Write an octet array contained inside a MB, this can be optimized
+ /// to minimize copies.
+ ACE_CDR::Boolean write_octet_array_mb (const ACE_Message_Block* mb);
+ //@}
+
+ /**
+ * Return 0 on failure and 1 on success.
+ */
+ //@{ @name Append contents of own CDR stream to another
+ ACE_CDR::Boolean append_boolean (ACE_InputCDR &);
+ ACE_CDR::Boolean append_char (ACE_InputCDR &);
+ ACE_CDR::Boolean append_wchar (ACE_InputCDR &);
+ ACE_CDR::Boolean append_octet (ACE_InputCDR &);
+ ACE_CDR::Boolean append_short (ACE_InputCDR &);
+ ACE_CDR::Boolean append_ushort (ACE_InputCDR &);
+ ACE_CDR::Boolean append_long (ACE_InputCDR &);
+ ACE_CDR::Boolean append_ulong (ACE_InputCDR &);
+ ACE_CDR::Boolean append_longlong (ACE_InputCDR &);
+ ACE_CDR::Boolean append_ulonglong (ACE_InputCDR &);
+ ACE_CDR::Boolean append_float (ACE_InputCDR &);
+ ACE_CDR::Boolean append_double (ACE_InputCDR &);
+ ACE_CDR::Boolean append_longdouble (ACE_InputCDR &);
+
+ ACE_CDR::Boolean append_wstring (ACE_InputCDR &);
+ ACE_CDR::Boolean append_string (ACE_InputCDR &);
+ //@}
+
+ /// Returns 0 if an error has ocurred, the only expected error is to
+ /// run out of memory.
+ int good_bit (void) const;
+
+ /// Reuse the CDR stream to write on the old buffer.
+ void reset (void);
+
+ /// Add the length of each message block in the chain.
+ size_t total_length (void) const;
+
+ /**
+ * Return the start of the message block chain for this CDR stream.
+ * NOTE: The complete CDR stream is represented by a chain of
+ * message blocks.
+ */
+ const ACE_Message_Block *begin (void) const;
+
+ /// Return the last message in the chain that is is use.
+ const ACE_Message_Block *end (void) const;
+
+ /// Return the <current_> message block in chain.
+ const ACE_Message_Block *current (void) const;
+
+ /**
+ * Access the underlying buffer (read only). NOTE: This
+ * method only returns a pointer to the first block in the
+ * chain.
+ */
+ const char *buffer (void) const;
+
+ /**
+ * Return the start and size of the internal buffer. NOTE: This
+ * method only returns information about the first block in the
+ * chain.
+ */
+ size_t length (void) const;
+
+ /**
+ * Utility function to allow the user more flexibility.
+ * Pads the stream up to the nearest <alignment>-byte boundary.
+ * Argument MUST be a power of 2.
+ * Returns 0 on success and -1 on failure.
+ */
+ int align_write_ptr (size_t alignment);
+
+ /// Access the codeset translators. They can be nil!
+ ACE_Char_Codeset_Translator *char_translator (void) const;
+ ACE_WChar_Codeset_Translator *wchar_translator (void) const;
+
+ /**
+ * Return alignment of the wr_ptr(), with respect to the start of
+ * the CDR stream. This is not the same as the alignment of
+ * current->wr_ptr()!
+ */
+ size_t current_alignment (void) const;
+
+ /**
+ * Returns (in <buf>) the next position in the buffer aligned to
+ * <size>, it advances the Message_Block wr_ptr past the data
+ * (i.e. <buf> + <size>). If necessary it grows the Message_Block
+ * buffer. Sets the good_bit to 0 and returns a -1 on failure.
+ */
+ int adjust (size_t size,
+ char *&buf);
+
+ /// As above, but now the size and alignment requirements may be
+ /// different.
+ int adjust (size_t size,
+ size_t align,
+ char *&buf);
+
+ /// If non-zero then this stream is writing in non-native byte order,
+ /// this is only meaningful if ACE_ENABLE_SWAP_ON_WRITE is defined.
+ int do_byte_swap (void) const;
+
+ /// For use by a gateway, which creates the output stream for the
+ /// reply to the client in its native byte order, but which must
+ /// send the reply in the byte order of the target's reply to the
+ /// gateway.
+ void reset_byte_order (int byte_order);
+
+ /// set GIOP version info
+ int set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor);
+
+private:
+ /// disallow copying...
+ ACE_OutputCDR (const ACE_OutputCDR& rhs);
+ ACE_OutputCDR& operator= (const ACE_OutputCDR& rhs);
+
+ ACE_CDR::Boolean write_1 (const ACE_CDR::Octet *x);
+ ACE_CDR::Boolean write_2 (const ACE_CDR::UShort *x);
+ ACE_CDR::Boolean write_4 (const ACE_CDR::ULong *x);
+ ACE_CDR::Boolean write_8 (const ACE_CDR::ULongLong *x);
+ ACE_CDR::Boolean write_16 (const ACE_CDR::LongDouble *x);
+
+ /**
+ * write an array of <length> elements, each of <size> bytes and the
+ * start aligned at a multiple of <align>. The elements are assumed
+ * to be packed with the right alignment restrictions. It is mostly
+ * designed for buffers of the basic types.
+ *
+ * This operation uses <memcpy>; as explained above it is expected
+ * that using assignment is faster that <memcpy> for one element,
+ * but for several elements <memcpy> should be more efficient, it
+ * could be interesting to find the break even point and optimize
+ * for that case, but that would be too platform dependent.
+ */
+ ACE_CDR::Boolean write_array (const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /**
+ * Grow the CDR stream. When it returns <buf> contains a pointer to
+ * memory in the CDR stream, with at least <size> bytes ahead of it
+ * and aligned to an <align> boundary. It moved the <wr_ptr> to <buf
+ * + size>.
+ */
+ int grow_and_adjust (size_t size,
+ size_t align,
+ char *&buf);
+
+private:
+ /// The start of the chain of message blocks.
+ ACE_Message_Block start_;
+
+ /// The current block in the chain were we are writing.
+ ACE_Message_Block *current_;
+
+ /**
+ * Is the current block writable. When we steal a buffer from the
+ * user and just chain it into the message block we are not supposed
+ * to write on it, even if it is past the start and end of the
+ * buffer.
+ */
+ int current_is_writable_;
+
+ /**
+ * The current alignment as measured from the start of the buffer.
+ * Usually this coincides with the alignment of the buffer in
+ * memory, but, when we chain another buffer this "quasi invariant"
+ * is broken.
+ * The current_alignment is used to readjust the buffer following
+ * the stolen message block.
+ */
+ size_t current_alignment_;
+
+ /**
+ * If not zero swap bytes at writing so the created CDR stream byte
+ * order does *not* match the machine byte order. The motivation
+ * for such a beast is that in some setting a few (fast) machines
+ * can be serving hundreds of slow machines with the opposite byte
+ * order, so it makes sense (as a load balancing device) to put the
+ * responsability in the writers. THIS IS NOT A STANDARD IN CORBA,
+ * USE AT YOUR OWN RISK
+ */
+ int do_byte_swap_;
+
+ /// Set to 0 when an error ocurrs.
+ int good_bit_;
+
+ /// Break-even point for copying.
+ size_t memcpy_tradeoff_;
+
+ /// GIOP version information
+ ACE_CDR::Octet major_version_;
+ ACE_CDR::Octet minor_version_;
+
+protected:
+ /// If not nil, invoke for translation of character and string data.
+ ACE_Char_Codeset_Translator *char_translator_;
+ ACE_WChar_Codeset_Translator *wchar_translator_;
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_InputCDR
+ *
+ * @brief A CDR stream for reading, i.e. for demarshalling.
+ *
+ * This class is based on the the CORBA spec for Java (98-02-29),
+ * java class omg.org.CORBA.portable.InputStream. It diverts in a
+ * few ways:
+ * + Operations to retrieve basic types take parameters by
+ * reference.
+ * + Operations taking arrays don't have offsets, because in C++
+ * it is easier to describe an array starting from x+offset.
+ * + Operations return an error status, because exceptions are
+ * not widely available in C++ (yet).
+ */
+class ACE_Export ACE_InputCDR
+{
+public:
+ /// The translator need privileged access to efficiently demarshal
+ /// arrays and the such
+ friend class ACE_Char_Codeset_Translator;
+ friend class ACE_WChar_Codeset_Translator;
+
+ /**
+ * Create an input stream from an arbitrary buffer. The buffer must
+ * be properly aligned because this contructor will *not* work if
+ * the buffer is aligned unproperly. See ACE_ptr_align_binary() for
+ * instructions on how to align a pointer properly and use
+ * ACE_CDR::MAX_ALIGNMENT for the correct alignment.
+ */
+ ACE_InputCDR (const char *buf,
+ size_t bufsiz,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Create an empty input stream. The caller is responsible for
+ /// putting the right data and providing the right alignment.
+ ACE_InputCDR (size_t bufsiz,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Create an input stream from an ACE_Message_Block
+ ACE_InputCDR (const ACE_Message_Block *data,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Create an input stream from an ACE_Data_Block. The <flag>
+ /// indicates whether the <data> can be deleted by the CDR stream
+ /// or not
+ ACE_InputCDR (ACE_Data_Block *data,
+ ACE_Message_Block::Message_Flags flag = 0,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /// Create an input stream from an ACE_Data_Block. It also sets the
+ /// read and write pointers at the desired positions. This would be
+ /// helpful if the applications desires to create a new CDR stream
+ /// from a semi-processed datablock.
+ ACE_InputCDR (ACE_Data_Block *data,
+ ACE_Message_Block::Message_Flags flag,
+ size_t read_pointer_position,
+ size_t write_pointer_position,
+ int byte_order = ACE_CDR_BYTE_ORDER,
+ ACE_CDR::Octet major_version =
+ ACE_CDR_GIOP_MAJOR_VERSION,
+ ACE_CDR::Octet minor_version =
+ ACE_CDR_GIOP_MINOR_VERSION);
+
+ /**
+ * These make a copy of the current stream state, but do not copy
+ * the internal buffer, so the same stream can be read multiple
+ * times efficiently.
+ */
+ ACE_InputCDR (const ACE_InputCDR& rhs);
+
+ ACE_InputCDR& operator= (const ACE_InputCDR& rhs);
+
+ /// When interpreting indirected TypeCodes it is useful to make a
+ /// "copy" of the stream starting in the new position.
+ ACE_InputCDR (const ACE_InputCDR& rhs,
+ size_t size,
+ ACE_CDR::Long offset);
+
+ /// This creates an encapsulated stream, the first byte must be (per
+ /// the spec) the byte order of the encapsulation.
+ ACE_InputCDR (const ACE_InputCDR& rhs,
+ size_t size);
+
+ /// Create an input CDR from an output CDR.
+ ACE_InputCDR (const ACE_OutputCDR& rhs,
+ ACE_Allocator* buffer_allocator = 0,
+ ACE_Allocator* data_block_allocator = 0,
+ ACE_Allocator* message_block_allocator = 0);
+
+ /// Helper class to transfer the contents from one input CDR to
+ /// another without requiring any extra memory allocations, data
+ /// copies or too many temporaries.
+ struct ACE_Export Transfer_Contents
+ {
+ Transfer_Contents (ACE_InputCDR &rhs);
+
+ ACE_InputCDR &rhs_;
+ };
+ /// Transfer the contents from <rhs> to a new CDR
+ ACE_InputCDR (Transfer_Contents rhs);
+
+ /// Destructor
+ ~ACE_InputCDR (void);
+
+ /// Disambiguate overloading when extracting octets, chars,
+ /// booleans, and bounded strings
+ //@{ @name Helper classes
+
+ struct ACE_Export to_boolean
+ {
+ to_boolean (ACE_CDR::Boolean &b);
+ ACE_CDR::Boolean &ref_;
+ };
+
+ struct ACE_Export to_char
+ {
+ to_char (ACE_CDR::Char &c);
+ ACE_CDR::Char &ref_;
+ };
+
+ struct ACE_Export to_wchar
+ {
+ to_wchar (ACE_CDR::WChar &wc);
+ ACE_CDR::WChar &ref_;
+ };
+
+ struct ACE_Export to_octet
+ {
+ to_octet (ACE_CDR::Octet &o);
+ ACE_CDR::Octet &ref_;
+ };
+
+ struct ACE_Export to_string
+ {
+ /// The constructor taking a non-const string is
+ /// now deprecated (C++ mapping 00-01-02), but we
+ /// keep it around for backward compatibility.
+ to_string (ACE_CDR::Char *&s,
+ ACE_CDR::ULong b);
+ to_string (const ACE_CDR::Char *&s,
+ ACE_CDR::ULong b);
+ const ACE_CDR::Char *&val_;
+ ACE_CDR::ULong bound_;
+ };
+
+ struct ACE_Export to_wstring
+ {
+ /// The constructor taking a non-const wstring is
+ /// now deprecated (C++ mapping 00-01-02), but we
+ /// keep it around for backward compatibility.
+ to_wstring (ACE_CDR::WChar *&ws,
+ ACE_CDR::ULong b);
+ to_wstring (const ACE_CDR::WChar *&ws,
+ ACE_CDR::ULong b);
+ const ACE_CDR::WChar *&val_;
+ ACE_CDR::ULong bound_;
+ };
+ //@}
+
+ /**
+ * Return 0 on failure and 1 on success.
+ */
+ //@{ @name Read basic IDL types
+ ACE_CDR::Boolean read_boolean (ACE_CDR::Boolean& x);
+ ACE_CDR::Boolean read_char (ACE_CDR::Char &x);
+ ACE_CDR::Boolean read_wchar (ACE_CDR::WChar& x);
+ ACE_CDR::Boolean read_octet (ACE_CDR::Octet& x);
+ ACE_CDR::Boolean read_short (ACE_CDR::Short &x);
+ ACE_CDR::Boolean read_ushort (ACE_CDR::UShort &x);
+ ACE_CDR::Boolean read_long (ACE_CDR::Long &x);
+ ACE_CDR::Boolean read_ulong (ACE_CDR::ULong &x);
+ ACE_CDR::Boolean read_longlong (ACE_CDR::LongLong& x);
+ ACE_CDR::Boolean read_ulonglong (ACE_CDR::ULongLong& x);
+ ACE_CDR::Boolean read_float (ACE_CDR::Float &x);
+ ACE_CDR::Boolean read_double (ACE_CDR::Double &x);
+ ACE_CDR::Boolean read_longdouble (ACE_CDR::LongDouble &x);
+
+ ACE_CDR::Boolean read_string (ACE_CDR::Char *&x);
+ ACE_CDR::Boolean read_string (ACE_CString &x);
+ ACE_CDR::Boolean read_wstring (ACE_CDR::WChar*& x);
+ //@}
+
+ /**
+ * The buffer <x> must be large enough to contain <length>
+ * elements.
+ * Return 0 on failure and 1 on success.
+ */
+ //@{ @name Read basic IDL types arrays
+ ACE_CDR::Boolean read_boolean_array (ACE_CDR::Boolean* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_char_array (ACE_CDR::Char *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_wchar_array (ACE_CDR::WChar* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_octet_array (ACE_CDR::Octet* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_short_array (ACE_CDR::Short *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_ushort_array (ACE_CDR::UShort *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_long_array (ACE_CDR::Long *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_ulong_array (ACE_CDR::ULong *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_longlong_array (ACE_CDR::LongLong* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_ulonglong_array (ACE_CDR::ULongLong* x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_float_array (ACE_CDR::Float *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_double_array (ACE_CDR::Double *x,
+ ACE_CDR::ULong length);
+ ACE_CDR::Boolean read_longdouble_array (ACE_CDR::LongDouble* x,
+ ACE_CDR::ULong length);
+ //@}
+
+ /**
+ * Return 0 on failure and 1 on success.
+ */
+ //@{ @name Skip elements
+ ACE_CDR::Boolean skip_boolean (void);
+ ACE_CDR::Boolean skip_char (void);
+ ACE_CDR::Boolean skip_wchar (void);
+ ACE_CDR::Boolean skip_octet (void);
+ ACE_CDR::Boolean skip_short (void);
+ ACE_CDR::Boolean skip_ushort (void);
+ ACE_CDR::Boolean skip_long (void);
+ ACE_CDR::Boolean skip_ulong (void);
+ ACE_CDR::Boolean skip_longlong (void);
+ ACE_CDR::Boolean skip_ulonglong (void);
+ ACE_CDR::Boolean skip_float (void);
+ ACE_CDR::Boolean skip_double (void);
+ ACE_CDR::Boolean skip_longdouble (void);
+ //@}
+
+ /**
+ * The next field must be a string, this method skips it. It is
+ * useful in parsing a TypeCode.
+ * Return 0 on failure and 1 on success.
+ */
+ ACE_CDR::Boolean skip_wstring (void);
+ ACE_CDR::Boolean skip_string (void);
+
+ /// Skip <n> bytes in the CDR stream.
+ /// Return 0 on failure and 1 on success.
+ ACE_CDR::Boolean skip_bytes (size_t n);
+
+ /// returns zero if a problem has been detected.
+ int good_bit (void) const;
+
+ /**
+ * Return the start of the message block chain for this CDR stream.
+ * NOTE: In the current implementation the chain has length 1, but
+ * we are planning to change that.
+ */
+ const ACE_Message_Block* start (void) const;
+
+ // = The following functions are useful to read the contents of the
+ // CDR stream from a socket or file.
+
+ /**
+ * Grow the internal buffer, reset <rd_ptr> to the first byte in the
+ * new buffer that is properly aligned, and set <wr_ptr> to <rd_ptr>
+ * + newsize
+ */
+ int grow (size_t newsize);
+
+ /**
+ * After reading and partially parsing the contents the user can
+ * detect a change in the byte order, this method will let him
+ * change it.
+ */
+ void reset_byte_order (int byte_order);
+
+ /// Re-initialize the CDR stream, copying the contents of the chain
+ /// of message_blocks starting from <data>.
+ void reset (const ACE_Message_Block *data,
+ int byte_order);
+
+ /// Steal the contents from the current CDR.
+ ACE_Message_Block *steal_contents (void);
+
+ /// Steal the contents of <cdr> and make a shallow copy into this
+ /// stream.
+ void steal_from (ACE_InputCDR &cdr);
+
+ /// Exchange data blocks with the caller of this method. The read
+ /// and write pointers are also exchanged.
+ /// Note: We now do only with the start_ message block.
+ void exchange_data_blocks (ACE_InputCDR &cdr);
+
+ /// Copy the data portion from the <cdr> to this cdr and return the
+ /// data content (ie. the ACE_Data_Block) from this CDR to the
+ /// caller. The caller is responsible for managing the memory of the
+ /// returned ACE_Data_Block.
+ ACE_Data_Block* clone_from (ACE_InputCDR &cdr);
+
+ /// Re-initialize the CDR stream, forgetting about the old contents
+ /// of the stream and allocating a new buffer (from the allocators).
+ void reset_contents (void);
+
+ /// Returns the current position for the rd_ptr....
+ char* rd_ptr (void);
+
+ /// Returns the current position for the wr_ptr....
+ char* wr_ptr (void);
+
+ /// Return how many bytes are left in the stream.
+ size_t length (void) const;
+
+ /**
+ * Utility function to allow the user more flexibility.
+ * Skips up to the nearest <alignment>-byte boundary.
+ * Argument MUST be a power of 2.
+ * Returns 0 on success and -1 on failure.
+ */
+ int align_read_ptr (size_t alignment);
+
+ /// If non-zero then this stream is writing in non-native byte order,
+ /// this is only meaningful if ACE_ENABLE_SWAP_ON_WRITE is defined.
+ int do_byte_swap (void) const;
+
+ /// If <do_byte_swap> returns 0, this returns ACE_CDR_BYTE_ORDER else
+ /// it returns !ACE_CDR_BYTE_ORDER.
+ int byte_order (void) const;
+
+ /// Access the codeset translators. They can be nil!
+ ACE_Char_Codeset_Translator *char_translator (void) const;
+ ACE_WChar_Codeset_Translator *wchar_translator (void) const;
+
+ /**
+ * Returns (in <buf>) the next position in the buffer aligned to
+ * <size>, it advances the Message_Block rd_ptr past the data
+ * (i.e. <buf> + <size>). Sets the good_bit to 0 and returns a -1
+ * on failure.
+ */
+ int adjust (size_t size,
+ char *&buf);
+
+ /// As above, but now the size and alignment requirements may be
+ /// different.
+ int adjust (size_t size,
+ size_t align,
+ char *&buf);
+
+protected:
+ /// The start of the chain of message blocks, even though in the
+ /// current version the chain always has length 1.
+ ACE_Message_Block start_;
+
+ /// The CDR stream byte order does not match the one on the machine,
+ /// swapping is needed while reading.
+ int do_byte_swap_;
+
+ /// set to 0 when an error occurs.
+ int good_bit_;
+
+ /// If not nil, invoke for translation of character and string data.
+ ACE_Char_Codeset_Translator *char_translator_;
+ ACE_WChar_Codeset_Translator *wchar_translator_;
+
+private:
+ ACE_CDR::Boolean read_1 (ACE_CDR::Octet *x);
+ ACE_CDR::Boolean read_2 (ACE_CDR::UShort *x);
+ ACE_CDR::Boolean read_4 (ACE_CDR::ULong *x);
+ ACE_CDR::Boolean read_8 (ACE_CDR::ULongLong *x);
+ ACE_CDR::Boolean read_16 (ACE_CDR::LongDouble *x);
+
+ // Several types can be read using the same routines, since TAO
+ // tries to use native types with known size for each CORBA type.
+ // We could use void* or char* to make the interface more
+ // consistent, but using native types let us exploit the strict
+ // alignment requirements of CDR streams and implement the
+ // operations using asignment.
+
+ /**
+ * Read an array of <length> elements, each of <size> bytes and the
+ * start aligned at a multiple of <align>. The elements are assumed
+ * to be packed with the right alignment restrictions. It is mostly
+ * designed for buffers of the basic types.
+ *
+ * This operation uses <memcpy>; as explained above it is expected
+ * that using assignment is faster that <memcpy> for one element,
+ * but for several elements <memcpy> should be more efficient, it
+ * could be interesting to find the break even point and optimize
+ * for that case, but that would be too platform dependent.
+ */
+ ACE_CDR::Boolean read_array (void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /// Move the rd_ptr ahead by <offset> bytes.
+ void rd_ptr (size_t offset);
+
+ /// Points to the continuation field of the current message block.
+ char* end (void);
+
+ ACE_CDR::Octet major_version_;
+ ACE_CDR::Octet minor_version_;
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_Char_Codeset_Translator
+ *
+ * @brief Codeset translation routines common to both Output and Input
+ * CDR streams.
+ *
+ * This class is a base class for defining codeset translation
+ * routines to handle the character set translations required by
+ * both CDR Input streams and CDR Output streams.
+ */
+class ACE_Export ACE_Char_Codeset_Translator
+{
+public:
+ /// Read a single character from the stream, converting from the
+ /// stream codeset to the native codeset
+ virtual ACE_CDR::Boolean read_char (ACE_InputCDR&,
+ ACE_CDR::Char&) = 0;
+
+ /// Read a string from the stream, including the length, converting
+ /// the characters from the stream codeset to the native codeset
+ virtual ACE_CDR::Boolean read_string (ACE_InputCDR&,
+ ACE_CDR::Char *&) = 0;
+
+ /// Read an array of characters from the stream, converting the
+ /// characters from the stream codeset to the native codeset.
+ virtual ACE_CDR::Boolean read_char_array (ACE_InputCDR&,
+ const ACE_CDR::Char*,
+ ACE_CDR::ULong) = 0;
+
+ /// Write a single character to the stream, converting from the
+ /// native codeset to the stream codeset
+ virtual ACE_CDR::Boolean write_char (ACE_OutputCDR&,
+ ACE_CDR::Char) = 0;
+
+ /// Write a string to the stream, including the length, converting
+ /// from the native codeset to the stream codeset
+ virtual ACE_CDR::Boolean write_string (ACE_OutputCDR&,
+ ACE_CDR::ULong,
+ const ACE_CDR::Char*) = 0;
+
+ /// Write an array of characters to the stream, converting from the
+ /// native codeset to the stream codeset
+ virtual ACE_CDR::Boolean write_char_array (ACE_OutputCDR&,
+ const ACE_CDR::Char*,
+ ACE_CDR::ULong) = 0;
+
+protected:
+ /// Children have access to low-level routines because they cannot
+ /// use read_char or something similar (it would recurse).
+ ACE_CDR::Boolean read_1 (ACE_InputCDR& input,
+ ACE_CDR::Octet *x);
+ ACE_CDR::Boolean write_1 (ACE_OutputCDR& output,
+ const ACE_CDR::Octet *x);
+
+ /// Efficiently read <length> elements of size <size> each from
+ /// <input> into <x>; the data must be aligned to <align>.
+ ACE_CDR::Boolean read_array (ACE_InputCDR& input,
+ void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /**
+ * Efficiently write <length> elements of size <size> from <x> into
+ * <output>. Before inserting the elements enough padding is added
+ * to ensure that the elements will be aligned to <align> in the
+ * stream.
+ */
+ ACE_CDR::Boolean write_array (ACE_OutputCDR& output,
+ const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /**
+ * Exposes the stream implementation of <adjust>, this is useful in
+ * many cases to minimize memory allocations during marshaling.
+ * On success <buf> will contain a contiguous area in the CDR stream
+ * that can hold <size> bytes aligned to <align>.
+ * Results
+ */
+ int adjust (ACE_OutputCDR& out,
+ size_t size,
+ size_t align,
+ char *&buf);
+
+ /// Used by derived classes to set errors in the CDR stream.
+ void good_bit (ACE_OutputCDR& out, int bit);
+};
+
+// ****************************************************************
+
+/**
+ * @class ACE_WChar_Codeset_Translator
+ *
+ * @brief Codeset translation routines common to both Output and Input
+ * CDR streams.
+ *
+ * This class is a base class for defining codeset translation
+ * routines to handle the character set translations required by
+ * both CDR Input streams and CDR Output streams.
+ */
+class ACE_Export ACE_WChar_Codeset_Translator
+{
+public:
+ virtual ACE_CDR::Boolean read_wchar (ACE_InputCDR&,
+ ACE_CDR::WChar&) = 0;
+ virtual ACE_CDR::Boolean read_wstring (ACE_InputCDR&,
+ ACE_CDR::WChar *&) = 0;
+ virtual ACE_CDR::Boolean read_wchar_array (ACE_InputCDR&,
+ const ACE_CDR::WChar*,
+ ACE_CDR::ULong) = 0;
+ virtual ACE_CDR::Boolean write_wchar (ACE_OutputCDR&,
+ ACE_CDR::WChar) = 0;
+ virtual ACE_CDR::Boolean write_wstring (ACE_OutputCDR&,
+ ACE_CDR::ULong,
+ const ACE_CDR::WChar*) = 0;
+ virtual ACE_CDR::Boolean write_wchar_array (ACE_OutputCDR&,
+ const ACE_CDR::WChar*,
+ ACE_CDR::ULong) = 0;
+
+protected:
+ /// Children have access to low-level routines because they cannot
+ /// use read_char or something similar (it would recurse).
+ ACE_CDR::Boolean read_1 (ACE_InputCDR& input,
+ ACE_CDR::Octet *x);
+ ACE_CDR::Boolean read_2 (ACE_InputCDR& input,
+ ACE_CDR::UShort *x);
+ ACE_CDR::Boolean read_4 (ACE_InputCDR& input,
+ ACE_CDR::ULong *x);
+ ACE_CDR::Boolean write_1 (ACE_OutputCDR& output,
+ const ACE_CDR::Octet *x);
+ ACE_CDR::Boolean write_2 (ACE_OutputCDR& output,
+ const ACE_CDR::UShort *x);
+ ACE_CDR::Boolean write_4 (ACE_OutputCDR& output,
+ const ACE_CDR::ULong *x);
+
+ /// Efficiently read <length> elements of size <size> each from
+ /// <input> into <x>; the data must be aligned to <align>.
+ ACE_CDR::Boolean read_array (ACE_InputCDR& input,
+ void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /**
+ * Efficiently write <length> elements of size <size> from <x> into
+ * <output>. Before inserting the elements enough padding is added
+ * to ensure that the elements will be aligned to <align> in the
+ * stream.
+ */
+ ACE_CDR::Boolean write_array (ACE_OutputCDR& output,
+ const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length);
+
+ /**
+ * Exposes the stream implementation of <adjust>, this is useful in
+ * many cases to minimize memory allocations during marshaling.
+ * On success <buf> will contain a contiguous area in the CDR stream
+ * that can hold <size> bytes aligned to <align>.
+ * Results
+ */
+ int adjust (ACE_OutputCDR& out,
+ size_t size,
+ size_t align,
+ char *&buf);
+
+ /// Used by derived classes to set errors in the CDR stream.
+ void good_bit (ACE_OutputCDR& out, int bit);
+};
+
+// @@ These operators should not be inlined since they force SString.h
+// to be included in this header.
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ const ACE_CString &x);
+
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CString &x);
+
+
+#if defined (__ACE_INLINE__)
+# include "ace/CDR_Stream.i"
+#else /* __ACE_INLINE__ */
+
+// Not used by CORBA or TAO
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::Char x);
+// CDR output operators for primitive types
+
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::Short x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::UShort x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::Long x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::ULong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::LongLong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::ULongLong x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR& os,
+ ACE_CDR::LongDouble x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::Float x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_CDR::Double x);
+
+// CDR output operator from helper classes
+
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_boolean x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_char x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_wchar x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_octet x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_string x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ ACE_OutputCDR::from_wstring x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ const ACE_CDR::Char* x);
+extern ACE_Export ACE_CDR::Boolean operator<< (ACE_OutputCDR &os,
+ const ACE_CDR::WChar* x);
+
+// Not used by CORBA or TAO
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Char &x);
+// CDR input operators for primitive types
+
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Short &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::UShort &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Long &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::ULong &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::LongLong &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::ULongLong &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::LongDouble &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Float &x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Double &x);
+
+// CDR input operator from helper classes
+
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_boolean x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_char x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_wchar x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_octet x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_string x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_InputCDR::to_wstring x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::Char*& x);
+extern ACE_Export ACE_CDR::Boolean operator>> (ACE_InputCDR &is,
+ ACE_CDR::WChar*& x);
+
+#endif /* __ACE_INLINE__ */
+
+#include "ace/post.h"
+
+#endif /* ACE_CDR_STREAM_H */
diff --git a/ace/Streams/CDR_Stream.i b/ace/Streams/CDR_Stream.i
new file mode 100644
index 00000000000..cfea878b357
--- /dev/null
+++ b/ace/Streams/CDR_Stream.i
@@ -0,0 +1,1493 @@
+// -*- C++ -*-
+// $Id$
+
+// ****************************************************************
+
+
+// implementing the special types
+ACE_INLINE
+ACE_OutputCDR::from_boolean::from_boolean (ACE_CDR::Boolean b)
+ : val_ (b)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_boolean::to_boolean (ACE_CDR::Boolean &b)
+ : ref_ (b)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_octet::from_octet (ACE_CDR::Octet o)
+ : val_ (o)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_octet::to_octet (ACE_CDR::Octet &o)
+ : ref_ (o)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_char::from_char (ACE_CDR::Char c)
+ : val_ (c)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_char::to_char (ACE_CDR::Char &c)
+ : ref_ (c)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_wchar::from_wchar (ACE_CDR::WChar wc)
+ : val_ (wc)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_wchar::to_wchar (ACE_CDR::WChar &wc)
+ : ref_ (wc)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_string::from_string (ACE_CDR::Char *s,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy)
+ : val_ (s),
+ bound_ (b),
+ nocopy_ (nocopy)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_string::from_string (const ACE_CDR::Char *s,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy)
+ : val_ (ACE_const_cast (ACE_CDR::Char *, s)),
+ bound_ (b),
+ nocopy_ (nocopy)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_string::to_string (ACE_CDR::Char *&s,
+ ACE_CDR::ULong b)
+ : val_ (ACE_const_cast (const ACE_CDR::Char *&, s)),
+ bound_ (b)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_string::to_string (const ACE_CDR::Char *&s,
+ ACE_CDR::ULong b)
+ : val_ (s),
+ bound_ (b)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_wstring::from_wstring (ACE_CDR::WChar *ws,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy)
+ : val_ (ws),
+ bound_ (b),
+ nocopy_ (nocopy)
+{
+}
+
+ACE_INLINE
+ACE_OutputCDR::from_wstring::from_wstring (const ACE_CDR::WChar *ws,
+ ACE_CDR::ULong b,
+ ACE_CDR::Boolean nocopy)
+ : val_ (ACE_const_cast (ACE_CDR::WChar *, ws)),
+ bound_ (b),
+ nocopy_ (nocopy)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_wstring::to_wstring (ACE_CDR::WChar *&ws,
+ ACE_CDR::ULong b)
+ : val_ (ACE_const_cast (const ACE_CDR::WChar *&, ws)),
+ bound_ (b)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::to_wstring::to_wstring (const ACE_CDR::WChar *&ws,
+ ACE_CDR::ULong b)
+ : val_ (ws),
+ bound_ (b)
+{
+}
+
+ACE_INLINE
+ACE_InputCDR::Transfer_Contents::Transfer_Contents (ACE_InputCDR &rhs)
+ : rhs_ (rhs)
+{
+}
+
+// ****************************************************************
+
+ACE_INLINE
+ACE_OutputCDR::~ACE_OutputCDR (void)
+{
+ if (this->start_.cont () != 0)
+ {
+ ACE_Message_Block::release (this->start_.cont ());
+ this->start_.cont (0);
+ }
+ this->current_ = 0;
+}
+
+ACE_INLINE void
+ACE_OutputCDR::reset (void)
+{
+ this->current_ = &this->start_;
+ this->current_is_writable_ = 1;
+ ACE_CDR::mb_align (&this->start_);
+ this->current_alignment_ = 0;
+
+ // It is tempting not to remove the memory, but we need to do so to
+ // release any potential user buffers chained in the continuation
+ // field.
+ ACE_Message_Block *cont = this->start_.cont ();
+ if (cont != 0)
+ {
+ ACE_Message_Block::release (cont);
+ this->start_.cont (0);
+ }
+
+}
+
+// Encode the CDR stream.
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_octet (ACE_CDR::Octet x)
+{
+ return this->write_1 (ACE_reinterpret_cast (const ACE_CDR::Octet *, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_boolean (ACE_CDR::Boolean x)
+{
+ return (ACE_CDR::Boolean) this->write_octet (x ? 1 : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_char (ACE_CDR::Char x)
+{
+ if (this->char_translator_ == 0)
+ return this->write_1 (ACE_reinterpret_cast (const ACE_CDR::Octet*, &x));
+ return this->char_translator_->write_char (*this, x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_short (ACE_CDR::Short x)
+{
+ return this->write_2 (ACE_reinterpret_cast (const ACE_CDR::UShort*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ushort (ACE_CDR::UShort x)
+{
+ return this->write_2 (ACE_reinterpret_cast (const ACE_CDR::UShort*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_long (ACE_CDR::Long x)
+{
+ return this->write_4 (ACE_reinterpret_cast (const ACE_CDR::ULong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulong (ACE_CDR::ULong x)
+{
+ return this->write_4 (ACE_reinterpret_cast (const ACE_CDR::ULong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longlong (const ACE_CDR::LongLong &x)
+{
+ return this->write_8 (ACE_reinterpret_cast (const ACE_CDR::ULongLong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulonglong (const ACE_CDR::ULongLong &x)
+{
+ return this->write_8 (ACE_reinterpret_cast (const ACE_CDR::ULongLong*,&x));
+}
+
+#if !defined (VXWORKS) || !defined (ghs)
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_float (ACE_CDR::Float x)
+{
+ return this->write_4 (ACE_reinterpret_cast (const ACE_CDR::ULong*, &x));
+}
+#endif /* !VXWORKS || !ghs */
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_double (const ACE_CDR::Double &x)
+{
+ return this->write_8 (ACE_reinterpret_cast (const ACE_CDR::ULongLong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longdouble (const ACE_CDR::LongDouble &x)
+{
+ return this->write_16 (ACE_reinterpret_cast (const ACE_CDR::LongDouble*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_string (const ACE_CDR::Char *x)
+{
+ if (x != 0)
+ return this->write_string (ACE_OS::strlen(x), x);
+ return this->write_string (0, 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_wstring (const ACE_CDR::WChar *x)
+{
+ if (x != 0)
+ return this->write_wstring (ACE_OS::wslen (x), x);
+ return this->write_wstring (0, 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_char_array (const ACE_CDR::Char *x,
+ ACE_CDR::ULong length)
+{
+ if (this->char_translator_ == 0)
+ return this->write_array (x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length);
+ return this->char_translator_->write_char_array (*this, x, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_wchar_array (const ACE_CDR::WChar* x,
+ ACE_CDR::ULong length)
+{
+ if (this->wchar_translator_ == 0)
+ return this->write_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+ return this->wchar_translator_->write_wchar_array (*this, x, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_octet_array (const ACE_CDR::Octet* x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_short_array (const ACE_CDR::Short *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ushort_array (const ACE_CDR::UShort *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_long_array (const ACE_CDR::Long *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulong_array (const ACE_CDR::ULong *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longlong_array (const ACE_CDR::LongLong *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_ulonglong_array (const ACE_CDR::ULongLong *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_float_array (const ACE_CDR::Float *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_double_array (const ACE_CDR::Double *x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::write_longdouble_array (const ACE_CDR::LongDouble* x,
+ ACE_CDR::ULong length)
+{
+ return this->write_array (x,
+ ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ length);
+}
+
+ACE_INLINE int
+ACE_OutputCDR::good_bit (void) const
+{
+ return this->good_bit_;
+}
+
+ACE_INLINE int
+ACE_OutputCDR::adjust (size_t size,
+ size_t align,
+ char*& buf)
+{
+ if (!this->current_is_writable_)
+ return this->grow_and_adjust (size, align, buf);
+
+ size_t offset =
+ ACE_align_binary (this->current_alignment_, align)
+ - this->current_alignment_;
+
+ buf = this->current_->wr_ptr () + offset;
+ char *end = buf + size;
+
+ if (end <= this->current_->end ())
+ {
+ this->current_alignment_ += offset + size;
+ this->current_->wr_ptr (end);
+ return 0;
+ }
+
+ return this->grow_and_adjust (size, align, buf);
+}
+
+ACE_INLINE int
+ACE_OutputCDR::adjust (size_t size, char*& buf)
+{
+ return this->adjust (size, size, buf);
+}
+
+ACE_INLINE int
+ACE_OutputCDR::set_version (ACE_CDR::Octet major, ACE_CDR::Octet minor)
+{
+ this->major_version_ = major;
+ this->minor_version_ = minor;
+ return 0;
+}
+
+ACE_INLINE const ACE_Message_Block*
+ACE_OutputCDR::begin (void) const
+{
+ return &this->start_;
+}
+
+ACE_INLINE const ACE_Message_Block*
+ACE_OutputCDR::end (void) const
+{
+ return this->current_->cont ();
+}
+
+ACE_INLINE const ACE_Message_Block*
+ACE_OutputCDR::current (void) const
+{
+ return this->current_;
+}
+
+ACE_INLINE size_t
+ACE_OutputCDR::total_length (void) const
+{
+ return ACE_CDR::total_length (this->begin (), this->end ());
+}
+
+ACE_INLINE const char*
+ACE_OutputCDR::buffer (void) const
+{
+ return this->start_.rd_ptr ();
+}
+
+ACE_INLINE size_t
+ACE_OutputCDR::length (void) const
+{
+ return this->start_.length ();
+}
+
+ACE_INLINE int
+ACE_OutputCDR::do_byte_swap (void) const
+{
+ return this->do_byte_swap_;
+}
+
+ACE_INLINE void
+ACE_OutputCDR::reset_byte_order (int byte_order)
+{
+ this->do_byte_swap_ = (byte_order != ACE_CDR_BYTE_ORDER);
+}
+
+ACE_INLINE size_t
+ACE_OutputCDR::current_alignment (void) const
+{
+ return this->current_alignment_;
+}
+
+ACE_INLINE int
+ACE_OutputCDR::align_write_ptr (size_t alignment)
+{
+ char *dummy;
+ return this->adjust (0, alignment, dummy);
+}
+
+ACE_INLINE ACE_Char_Codeset_Translator *
+ACE_OutputCDR::char_translator (void) const
+{
+ return this->char_translator_;
+}
+
+ACE_INLINE ACE_WChar_Codeset_Translator *
+ACE_OutputCDR::wchar_translator (void) const
+{
+ return this->wchar_translator_;
+}
+
+// ****************************************************************
+
+ACE_INLINE
+ACE_InputCDR::~ACE_InputCDR (void)
+{
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_octet (ACE_CDR::Octet& x)
+{
+ return this->read_1 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_boolean (ACE_CDR::Boolean& x)
+{
+ ACE_CDR::Octet tmp;
+ this->read_octet (tmp);
+ x = tmp ? 1 : 0;
+ return (ACE_CDR::Boolean) this->good_bit_;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_char (ACE_CDR::Char &x)
+{
+ if (this->char_translator_ == 0)
+ return this->read_1 (ACE_reinterpret_cast (ACE_CDR::Octet*, &x));
+ return this->char_translator_->read_char (*this, x);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_short (ACE_CDR::Short &x)
+{
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ushort (ACE_CDR::UShort &x)
+{
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*, &x));
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_long (ACE_CDR::Long &x)
+{
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*, &x));
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulong (ACE_CDR::ULong &x)
+{
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*, &x));
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longlong (ACE_CDR::LongLong &x)
+{
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulonglong (ACE_CDR::ULongLong &x)
+{
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*,&x));
+}
+
+#if !defined (VXWORKS) || !defined (ghs)
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_float (ACE_CDR::Float &x)
+{
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*, &x));
+}
+#endif /* !VXWORKS || !ghs */
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_double (ACE_CDR::Double &x)
+{
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*, &x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longdouble (ACE_CDR::LongDouble &x)
+{
+ return this->read_16 (ACE_reinterpret_cast (ACE_CDR::LongDouble*,&x));
+}
+
+ACE_INLINE size_t
+ACE_InputCDR::length (void) const
+{
+ return this->start_.length ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_char_array (ACE_CDR::Char* x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ if (this->char_translator_ == 0)
+ return this->read_array (x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length);
+ return this->char_translator_->read_char_array (*this, x, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_wchar_array (ACE_CDR::WChar* x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ if (this->wchar_translator_ == 0)
+ return this->read_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+ return this->wchar_translator_->read_wchar_array (*this, x, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_octet_array (ACE_CDR::Octet* x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::OCTET_SIZE,
+ ACE_CDR::OCTET_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_short_array (ACE_CDR::Short *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ushort_array (ACE_CDR::UShort *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::SHORT_SIZE,
+ ACE_CDR::SHORT_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_long_array (ACE_CDR::Long *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulong_array (ACE_CDR::ULong *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longlong_array (ACE_CDR::LongLong *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_ulonglong_array (ACE_CDR::ULongLong *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_float_array (ACE_CDR::Float *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONG_SIZE,
+ ACE_CDR::LONG_ALIGN,
+ length);
+}
+
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_double_array (ACE_CDR::Double *x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONGLONG_SIZE,
+ ACE_CDR::LONGLONG_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::read_longdouble_array (ACE_CDR::LongDouble* x,
+ ACE_CDR::ULong length)
+{
+ // Make sure the length of the array isn't greater than the length of
+ // the stream.
+ if (length > this->length())
+ return 0;
+
+ return this->read_array (x,
+ ACE_CDR::LONGDOUBLE_SIZE,
+ ACE_CDR::LONGDOUBLE_ALIGN,
+ length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_char (void)
+{
+ ACE_CDR::Char x;
+ return this->read_1 (ACE_reinterpret_cast (ACE_CDR::Octet*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_octet (void)
+{
+ ACE_CDR::Octet x;
+ return this->read_1 (&x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_boolean (void)
+{
+ ACE_CDR::Octet tmp;
+ this->read_octet (tmp);
+ return this->good_bit_;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_short (void)
+{
+ ACE_CDR::Short x;
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ushort (void)
+{
+ ACE_CDR::UShort x;
+ return this->read_2 (ACE_reinterpret_cast (ACE_CDR::UShort*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_long (void)
+{
+ ACE_CDR::Long x;
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ulong (void)
+{
+ ACE_CDR::ULong x;
+ return this->read_4 (ACE_reinterpret_cast (ACE_CDR::ULong*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_longlong (void)
+{
+ ACE_CDR::LongLong x;
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_ulonglong (void)
+{
+ ACE_CDR::ULongLong x;
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_float (void)
+{
+ // Changing this removes the warning for GHS and it
+ // stops the compiler from getting an internal error.
+ ACE_CDR::ULong value;
+ return this->read_4 (&value);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_double (void)
+{
+ double x;
+ return this->read_8 (ACE_reinterpret_cast (ACE_CDR::ULongLong*,&x));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_InputCDR::skip_longdouble (void)
+{
+ ACE_CDR::LongDouble x;
+ return this->read_16 (ACE_reinterpret_cast (ACE_CDR::LongDouble*,&x));
+}
+
+ACE_INLINE char*
+ACE_InputCDR::end (void)
+{
+ return this->start_.end ();
+}
+
+ACE_INLINE void
+ACE_InputCDR::rd_ptr (size_t offset)
+{
+ this->start_.rd_ptr (offset);
+}
+
+ACE_INLINE char*
+ACE_InputCDR::rd_ptr (void)
+{
+ return this->start_.rd_ptr ();
+}
+
+ACE_INLINE char*
+ACE_InputCDR::wr_ptr (void)
+{
+ return this->start_.wr_ptr ();
+}
+
+ACE_INLINE int
+ACE_InputCDR::adjust (size_t size,
+ size_t align,
+ char*& buf)
+{
+ buf = ACE_ptr_align_binary (this->rd_ptr (), align);
+ char *end = buf + size;
+ if (end <= this->wr_ptr ())
+ {
+ this->start_.rd_ptr (end);
+ return 0;
+ }
+
+ this->good_bit_ = 0;
+ return -1;
+}
+
+ACE_INLINE int
+ACE_InputCDR::adjust (size_t size,
+ char*& buf)
+{
+ return this->adjust (size, size, buf);
+}
+
+ACE_INLINE const ACE_Message_Block*
+ACE_InputCDR::start (void) const
+{
+ return &this->start_;
+}
+
+ACE_INLINE int
+ACE_InputCDR::good_bit (void) const
+{
+ return this->good_bit_;
+}
+
+// ****************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Char x)
+{
+ os.write_char (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Short x)
+{
+ os.write_short (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::UShort x)
+{
+ os.write_ushort (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Long x)
+{
+ os.write_long (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::ULong x)
+{
+ os.write_ulong (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::LongLong x)
+{
+ os.write_longlong (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::ULongLong x)
+{
+ os.write_ulonglong (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::LongDouble x)
+{
+ os.write_longdouble (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Float x)
+{
+ os.write_float (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_CDR::Double x)
+{
+ os.write_double (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, const ACE_CDR::Char *x)
+{
+ os.write_string (x);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, const ACE_CDR::WChar *x)
+{
+ os.write_wstring (x);
+ return os.good_bit ();
+}
+
+// The following use the helper classes
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_boolean x)
+{
+ os.write_boolean (x.val_);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_char x)
+{
+ os.write_char (x.val_);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_wchar x)
+{
+ os.write_wchar (x.val_);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_octet x)
+{
+ os.write_octet (x.val_);
+ return os.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_string x)
+{
+ ACE_CDR::ULong len = 0;
+ if (x.val_ != 0)
+ len = ACE_OS::strlen (x.val_);
+ os.write_string (len, x.val_);
+ return os.good_bit () && (len <= x.bound_);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator<< (ACE_OutputCDR &os, ACE_OutputCDR::from_wstring x)
+{
+ ACE_CDR::ULong len = 0;;
+ if (x.val_ != 0)
+ len = ACE_OS::wslen (x.val_);
+ os.write_wstring (len, x.val_);
+ return os.good_bit () && (len <= x.bound_);
+}
+
+// ****************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Char &x)
+{
+ is.read_char (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Short &x)
+{
+ is.read_short (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::UShort &x)
+{
+ is.read_ushort (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>>(ACE_InputCDR &is, ACE_CDR::Long &x)
+{
+ is.read_long (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::ULong &x)
+{
+ is.read_ulong (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::LongLong &x)
+{
+ is.read_longlong (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::ULongLong &x)
+{
+ is.read_ulonglong (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR& is, ACE_CDR::LongDouble &x)
+{
+ is.read_longdouble (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Float &x)
+{
+ is.read_float (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Double &x)
+{
+ is.read_double (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::Char *&x)
+{
+ is.read_string (x);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_CDR::WChar *&x)
+{
+ is.read_wstring (x);
+ return is.good_bit ();
+}
+
+// The following use the helper classes
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_boolean x)
+{
+ is.read_boolean (x.ref_);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_char x)
+{
+ is.read_char (x.ref_);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_wchar x)
+{
+ is.read_wchar (x.ref_);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_octet x)
+{
+ is.read_octet (x.ref_);
+ return is.good_bit ();
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_string x)
+{
+ is.read_string (ACE_const_cast (char *&, x.val_));
+ // check if the bounds are satisfied
+ return (is.good_bit () &&
+ (ACE_OS::strlen (x.val_) <= x.bound_));
+}
+
+ACE_INLINE ACE_CDR::Boolean
+operator>> (ACE_InputCDR &is, ACE_InputCDR::to_wstring x)
+{
+ is.read_wstring (ACE_const_cast (ACE_CDR::WChar *&, x.val_));
+ // check if the bounds are satisfied
+ return (is.good_bit () &&
+ (ACE_OS::wslen (x.val_) <= x.bound_));
+}
+
+// ***************************************************************************
+// We must define these methods here because they use the "read_*" inlined
+// methods of the ACE_InputCDR class
+// ***************************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_boolean (ACE_InputCDR &stream)
+{
+ ACE_CDR::Boolean x;
+ return (stream.read_boolean (x) ? this->write_boolean (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_char (ACE_InputCDR &stream)
+{
+ ACE_CDR::Char x;
+ return (stream.read_char (x) ? this->write_char (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_wchar (ACE_InputCDR &stream)
+{
+ ACE_CDR::WChar x;
+ return (stream.read_wchar (x) ? this->write_wchar (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_octet (ACE_InputCDR &stream)
+{
+ ACE_CDR::Octet x;
+ return (stream.read_octet (x) ? this->write_octet (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_short (ACE_InputCDR &stream)
+{
+ ACE_CDR::Short x;
+ return (stream.read_short (x) ? this->write_short (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_ushort (ACE_InputCDR &stream)
+{
+ ACE_CDR::UShort x;
+ return (stream.read_ushort (x) ? this->write_ushort (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_long (ACE_InputCDR &stream)
+{
+ ACE_CDR::Long x;
+ return (stream.read_long (x) ? this->write_long (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_ulong (ACE_InputCDR &stream)
+{
+ ACE_CDR::ULong x;
+ return (stream.read_ulong (x) ? this->write_ulong (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_longlong (ACE_InputCDR &stream)
+{
+ ACE_CDR::LongLong x;
+ return (stream.read_longlong (x) ? this->write_longlong (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_ulonglong (ACE_InputCDR &stream)
+{
+ ACE_CDR::ULongLong x;
+ return (stream.read_ulonglong (x) ? this->write_ulonglong (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_float (ACE_InputCDR &stream)
+{
+ ACE_CDR::Float x;
+ return (stream.read_float (x) ? this->write_float (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_double (ACE_InputCDR &stream)
+{
+ ACE_CDR::Double x;
+ return (stream.read_double (x) ? this->write_double (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_longdouble (ACE_InputCDR &stream)
+{
+ ACE_CDR::LongDouble x;
+ return (stream.read_longdouble (x) ? this->write_longdouble (x) : 0);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_string (ACE_InputCDR &stream)
+{
+ ACE_CDR::Char *x;
+ ACE_CDR::Boolean flag =
+ (stream.read_string (x) ? this->write_string (x) : 0);
+ delete [] x;
+ return flag;
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_OutputCDR::append_wstring (ACE_InputCDR &stream)
+{
+ ACE_CDR::WChar *x;
+ ACE_CDR::Boolean flag =
+ (stream.read_wstring (x) ? this->write_wstring (x) : 0);
+ delete [] x;
+ return flag;
+}
+
+ACE_INLINE void
+ACE_InputCDR::reset_byte_order (int byte_order)
+{
+ this->do_byte_swap_ = (byte_order != ACE_CDR_BYTE_ORDER);
+}
+
+ACE_INLINE int
+ACE_InputCDR::do_byte_swap (void) const
+{
+ return this->do_byte_swap_;
+}
+
+ACE_INLINE int
+ACE_InputCDR::byte_order (void) const
+{
+ if (this->do_byte_swap ())
+ return !ACE_CDR_BYTE_ORDER;
+ else
+ return ACE_CDR_BYTE_ORDER;
+}
+
+ACE_INLINE int
+ACE_InputCDR::align_read_ptr (size_t alignment)
+{
+ char *buf = ACE_ptr_align_binary (this->rd_ptr (),
+ alignment);
+
+ if (buf <= this->wr_ptr ())
+ {
+ this->start_.rd_ptr (buf);
+ return 0;
+ }
+
+ this->good_bit_ = 0;
+ return -1;
+}
+
+ACE_INLINE ACE_Char_Codeset_Translator *
+ACE_InputCDR::char_translator (void) const
+{
+ return this->char_translator_;
+}
+
+ACE_INLINE ACE_WChar_Codeset_Translator *
+ACE_InputCDR::wchar_translator (void) const
+{
+ return this->wchar_translator_;
+}
+
+// ****************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_Char_Codeset_Translator::read_1 (ACE_InputCDR& input,
+ ACE_CDR::Octet *x)
+{
+ return input.read_1 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_Char_Codeset_Translator::write_1 (ACE_OutputCDR& output,
+ const ACE_CDR::Octet *x)
+{
+ return output.write_1 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_Char_Codeset_Translator::read_array (ACE_InputCDR& in,
+ void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ return in.read_array (x, size, align, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_Char_Codeset_Translator::write_array (ACE_OutputCDR& out,
+ const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ return out.write_array(x, size, align, length);
+}
+
+ACE_INLINE int
+ACE_Char_Codeset_Translator::adjust (ACE_OutputCDR& out,
+ size_t size,
+ size_t align,
+ char *&buf)
+{
+ return out.adjust(size, align, buf);
+}
+
+ACE_INLINE void
+ACE_Char_Codeset_Translator::good_bit (ACE_OutputCDR& out, int bit)
+{
+ out.good_bit_ = bit;
+}
+
+// ****************************************************************
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::read_1 (ACE_InputCDR& input,
+ ACE_CDR::Octet *x)
+{
+ return input.read_1 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::read_2 (ACE_InputCDR& input,
+ ACE_CDR::UShort *x)
+{
+ return input.read_2 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::read_4 (ACE_InputCDR& input,
+ ACE_CDR::ULong *x)
+{
+ return input.read_4 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::write_1 (ACE_OutputCDR& output,
+ const ACE_CDR::Octet *x)
+{
+ return output.write_1 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::write_2 (ACE_OutputCDR& output,
+ const ACE_CDR::UShort *x)
+{
+ return output.write_2 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::write_4 (ACE_OutputCDR& output,
+ const ACE_CDR::ULong *x)
+{
+ return output.write_4 (x);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::read_array (ACE_InputCDR& in,
+ void* x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ return in.read_array (x, size, align, length);
+}
+
+ACE_INLINE ACE_CDR::Boolean
+ACE_WChar_Codeset_Translator::write_array (ACE_OutputCDR& out,
+ const void *x,
+ size_t size,
+ size_t align,
+ ACE_CDR::ULong length)
+{
+ return out.write_array(x, size, align, length);
+}
+
+ACE_INLINE int
+ACE_WChar_Codeset_Translator::adjust (ACE_OutputCDR& out,
+ size_t size,
+ size_t align,
+ char *&buf)
+{
+ return out.adjust(size, align, buf);
+}
+
+ACE_INLINE void
+ACE_WChar_Codeset_Translator::good_bit (ACE_OutputCDR& out, int bit)
+{
+ out.good_bit_ = bit;
+}